如何正确使用Ansible uri模块的form-multipart格式向FusionLayer Infinity提交DNS更新?
Let's break down what's going wrong here and how to fix it.
First, the error message "failed to parse body as form-multipart: at least one of filename or content must be provided" is telling you exactly what's missing: when using body_format: form-multipart, Ansible expects each form field to either reference a file (via filename) or explicitly provide the string content of the field. Your current setup passes a dictionary directly to the add field, which Ansible tries to interpret as a file upload structure instead of a plain string value.
Your target curl command uses --form add='{"name": "...", ...}' to send a JSON string as the value of the add form field. To replicate this in Ansible, you need to explicitly define the content (and optionally content_type) for the add field.
Solution 1: Explicit Content with String JSON
Modify your playbook to wrap the JSON string in a content key under the add field, and specify the correct MIME type:
- name: Add DNS records ansible.builtin.uri: url: "{{ infinity.url_base }}/zones/{{ infinity.zone_id }}" user: "{{ user_infinity.user }}" password: "{{ user_infinity.pass }}" method: PUT body_format: form-multipart body: add: content: '{"name": "{{ item }}", "type": "A", "value": "{{ app_hosts[item] }}"}' content_type: application/json with_items: "{{ app_hosts }}"
Solution 2: Safer JSON Generation with to_json Filter
To avoid potential syntax errors from manual JSON string concatenation (e.g., if item or app_hosts[item] contains quotes), use Ansible's to_json filter to convert a dictionary to a valid JSON string:
- name: Add DNS records ansible.builtin.uri: url: "{{ infinity.url_base }}/zones/{{ infinity.zone_id }}" user: "{{ user_infinity.user }}" password: "{{ user_infinity.pass }}" method: PUT body_format: form-multipart body: add: content: "{{ {'name': item, 'type': 'A', 'value': app_hosts[item]} | to_json }}" content_type: application/json with_items: "{{ app_hosts }}"
Why This Works
Both approaches tell Ansible to treat the add field as a string value (the JSON payload) rather than a file upload. The content_type: application/json ensures the server receives the field with the correct MIME type, matching exactly what your curl command sends.
Looking at your invocation output, you'll notice that originally the add value was being parsed as a nested dictionary:
"add": { "name": "recordname", "type": "A", "value": "10.5.13.15" }
With the fix, Ansible will send the add field as a single JSON string, just like your curl command does.
内容的提问来源于stack exchange,提问作者Onni

