2026-04-01 23:55:05 +00:00
|
|
|
package ansible
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"io"
|
|
|
|
|
"io/fs"
|
|
|
|
|
"sync"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type becomeRecordingClient struct {
|
|
|
|
|
mu sync.Mutex
|
|
|
|
|
become bool
|
|
|
|
|
becomeUser string
|
|
|
|
|
becomePass string
|
|
|
|
|
runBecomeSeen []bool
|
2026-04-02 14:46:35 +00:00
|
|
|
runBecomePass []string
|
2026-04-01 23:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) Run(_ context.Context, _ string) (string, string, int, error) {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
c.runBecomeSeen = append(c.runBecomeSeen, c.become)
|
2026-04-02 14:46:35 +00:00
|
|
|
c.runBecomePass = append(c.runBecomePass, c.becomePass)
|
2026-04-01 23:55:05 +00:00
|
|
|
return "", "", 0, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) RunScript(_ context.Context, _ string) (string, string, int, error) {
|
|
|
|
|
return c.Run(context.Background(), "")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) Upload(_ context.Context, _ io.Reader, _ string, _ fs.FileMode) error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) Download(_ context.Context, _ string) ([]byte, error) {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) FileExists(_ context.Context, _ string) (bool, error) {
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) Stat(_ context.Context, _ string) (map[string]any, error) {
|
|
|
|
|
return map[string]any{}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) BecomeState() (bool, string, string) {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
return c.become, c.becomeUser, c.becomePass
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) SetBecome(become bool, user, password string) {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
c.become = become
|
2026-04-03 11:41:04 +00:00
|
|
|
if !become {
|
|
|
|
|
c.becomeUser = ""
|
|
|
|
|
c.becomePass = ""
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-04-01 23:55:05 +00:00
|
|
|
if user != "" {
|
|
|
|
|
c.becomeUser = user
|
|
|
|
|
}
|
|
|
|
|
if password != "" {
|
|
|
|
|
c.becomePass = password
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *becomeRecordingClient) Close() error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestExecutor_RunTaskOnHost_Good_TaskBecomeFalseOverridesPlayBecome(t *testing.T) {
|
|
|
|
|
e := NewExecutor("/tmp")
|
|
|
|
|
e.SetInventoryDirect(&Inventory{
|
|
|
|
|
All: &InventoryGroup{
|
|
|
|
|
Hosts: map[string]*Host{
|
|
|
|
|
"host1": {AnsibleHost: "127.0.0.1"},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
client := &becomeRecordingClient{}
|
|
|
|
|
client.SetBecome(true, "root", "secret")
|
|
|
|
|
e.clients["host1"] = client
|
|
|
|
|
|
|
|
|
|
play := &Play{Become: true, BecomeUser: "admin"}
|
|
|
|
|
task := &Task{
|
|
|
|
|
Name: "Disable become for this task",
|
|
|
|
|
Module: "command",
|
|
|
|
|
Args: map[string]any{"cmd": "echo ok"},
|
|
|
|
|
Become: func() *bool { v := false; return &v }(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.NoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play))
|
|
|
|
|
require.Len(t, client.runBecomeSeen, 1)
|
|
|
|
|
assert.False(t, client.runBecomeSeen[0])
|
|
|
|
|
assert.True(t, client.become)
|
2026-04-02 13:25:00 +00:00
|
|
|
assert.Equal(t, "admin", client.becomeUser)
|
2026-04-01 23:55:05 +00:00
|
|
|
assert.Equal(t, "secret", client.becomePass)
|
|
|
|
|
}
|
2026-04-02 14:46:35 +00:00
|
|
|
|
|
|
|
|
func TestExecutor_RunTaskOnHost_Good_TaskBecomeUsesInventoryPassword(t *testing.T) {
|
|
|
|
|
e := NewExecutor("/tmp")
|
|
|
|
|
e.SetInventoryDirect(&Inventory{
|
|
|
|
|
All: &InventoryGroup{
|
|
|
|
|
Hosts: map[string]*Host{
|
|
|
|
|
"host1": {
|
|
|
|
|
AnsibleHost: "127.0.0.1",
|
|
|
|
|
AnsibleBecomePassword: "secret",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
client := &becomeRecordingClient{}
|
|
|
|
|
e.clients["host1"] = client
|
|
|
|
|
|
|
|
|
|
play := &Play{}
|
|
|
|
|
task := &Task{
|
|
|
|
|
Name: "Enable become for this task",
|
|
|
|
|
Module: "command",
|
|
|
|
|
Args: map[string]any{"cmd": "echo ok"},
|
|
|
|
|
Become: func() *bool { v := true; return &v }(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.NoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play))
|
|
|
|
|
require.Len(t, client.runBecomeSeen, 1)
|
|
|
|
|
assert.True(t, client.runBecomeSeen[0])
|
|
|
|
|
require.Len(t, client.runBecomePass, 1)
|
|
|
|
|
assert.Equal(t, "secret", client.runBecomePass[0])
|
|
|
|
|
}
|