feat(ansible): support uri src request bodies
Some checks are pending
CI / test (push) Waiting to run
CI / auto-fix (push) Waiting to run
CI / auto-merge (push) Waiting to run

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-03 15:13:22 +00:00
parent 9b7f411763
commit f637f0df98
3 changed files with 37 additions and 2 deletions

View file

@ -526,6 +526,7 @@ type sshRunner interface {
Run(ctx context.Context, cmd string) (string, string, int, error)
RunScript(ctx context.Context, script string) (string, string, int, error)
Upload(ctx context.Context, local io.Reader, remote string, mode fs.FileMode) error
Download(ctx context.Context, remote string) ([]byte, error)
}
type sshFileTransferRunner interface {
@ -2011,6 +2012,7 @@ func moduleURIWithClient(_ *Executor, client sshRunner, args map[string]any) (*T
forceBasicAuth := getBoolArg(args, "force_basic_auth", false)
unixSocket := getStringArg(args, "unix_socket", "")
followRedirects := lower(getStringArg(args, "follow_redirects", "safe"))
src := getStringArg(args, "src", "")
if url == "" {
return nil, mockError("moduleURIWithClient", "uri: url required")
@ -2047,7 +2049,13 @@ func moduleURIWithClient(_ *Executor, client sshRunner, args map[string]any) (*T
curlOpts = appendURIFollowRedirects(curlOpts, method, followRedirects)
// Body
if body := args["body"]; body != nil {
if src != "" {
bodyBytes, err := client.Download(context.Background(), src)
if err != nil {
return nil, mockWrap("moduleURIWithClient", "download src", err)
}
curlOpts = append(curlOpts, "-d", sprintf("%q", string(bodyBytes)))
} else if body := args["body"]; body != nil {
bodyText, err := renderURIBody(body, bodyFormat)
if err != nil {
return nil, mockWrap("moduleURIWithClient", "render body", err)

View file

@ -2022,6 +2022,7 @@ func (e *Executor) moduleURI(ctx context.Context, client sshExecutorClient, args
forceBasicAuth := getBoolArg(args, "force_basic_auth", false)
unixSocket := getStringArg(args, "unix_socket", "")
followRedirects := lower(getStringArg(args, "follow_redirects", "safe"))
src := getStringArg(args, "src", "")
if url == "" {
return nil, coreerr.E("Executor.moduleURI", "url required", nil)
@ -2060,7 +2061,13 @@ func (e *Executor) moduleURI(ctx context.Context, client sshExecutorClient, args
curlOpts = appendURIFollowRedirects(curlOpts, method, followRedirects)
// Body
if body := args["body"]; body != nil {
if src != "" {
bodyBytes, err := client.Download(ctx, src)
if err != nil {
return nil, coreerr.E("Executor.moduleURI", "download src", err)
}
curlOpts = append(curlOpts, "-d", sprintf("%q", string(bodyBytes)))
} else if body := args["body"]; body != nil {
bodyText, err := renderURIBody(body, bodyFormat)
if err != nil {
return nil, coreerr.E("Executor.moduleURI", "render body", err)

View file

@ -1689,6 +1689,26 @@ func TestModulesAdv_ModuleURI_Good_UsesUnixSocket(t *testing.T) {
assert.True(t, mock.hasExecuted(`--unix-socket '/var/run/docker.sock'`))
}
func TestModulesAdv_ModuleURI_Good_UsesSourceFileBody(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
require.NoError(t, mock.Upload(context.Background(), newReader("alpha=1&beta=2"), "/tmp/request-body.txt", 0644))
mock.expectCommand(`curl.*form\.example\.com`, "created\n201", "", 0)
result, err := moduleURIWithClient(e, mock, map[string]any{
"url": "https://form.example.com/submit",
"method": "POST",
"src": "/tmp/request-body.txt",
"body_format": "json",
"status_code": 201,
})
require.NoError(t, err)
assert.False(t, result.Failed)
assert.Equal(t, 201, result.RC)
assert.True(t, mock.containsSubstring(`-d "alpha=1&beta=2"`))
assert.False(t, mock.containsSubstring("Content-Type: application/json"))
}
func TestModulesAdv_ModuleURI_Good_FormURLEncodedBody(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
mock.expectCommand(`curl.*form\.example\.com`, "created\n201", "", 0)