From df7984d6ac9a6551936f82a79bd328aecfc4b4d6 Mon Sep 17 00:00:00 2001 From: Florian Kinder Date: Sat, 8 Nov 2025 10:12:33 +0100 Subject: [PATCH 1/3] Fix Vultr startup script JSON serialization error The startup_script module was failing with "Object of type 'bytes' is not JSON serializable" because the lookup('template', ...) was returning bytes instead of a string. Added | string filter to explicitly convert the template result to a string, matching the pattern used by the DigitalOcean cloud provider. Also simplified from multiline block format to inline format for consistency with other cloud providers. Fixes the error: "Object of type 'bytes' is not JSON serializable by the 'tagless' profile." --- roles/cloud-vultr/tasks/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/roles/cloud-vultr/tasks/main.yml b/roles/cloud-vultr/tasks/main.yml index ccbcd13b6..2833abd56 100644 --- a/roles/cloud-vultr/tasks/main.yml +++ b/roles/cloud-vultr/tasks/main.yml @@ -28,8 +28,7 @@ - name: Upload the startup script vultr.cloud.startup_script: name: algo-startup - script: | - {{ lookup('template', 'files/cloud-init/base.yml') }} + script: "{{ lookup('template', 'files/cloud-init/base.yml') | string }}" - name: Creating a server vultr.cloud.instance: From 19c22d81a63814f5e1aac0b06f36cc3672ae3da4 Mon Sep 17 00:00:00 2001 From: Florian Kinder Date: Sat, 8 Nov 2025 10:16:02 +0100 Subject: [PATCH 2/3] Add string filters to template lookups in cloud-init base template Added | string filters to lookup() calls in the cloud-init base template to ensure consistent string handling across all cloud providers. The Vultr startup_script module requires all values to be JSON-serializable strings, and lookup() can return bytes in some contexts. This change ensures that both the SSH config template lookup and the SSH public key file lookup explicitly return strings. This is a defensive fix that improves compatibility with strict JSON serialization requirements in some Ansible modules, while remaining backward compatible with existing cloud providers. Related to: vultr.cloud.startup_script JSON serialization requirements --- files/cloud-init/base.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/cloud-init/base.yml b/files/cloud-init/base.yml index 600269079..b5398613f 100644 --- a/files/cloud-init/base.yml +++ b/files/cloud-init/base.yml @@ -30,12 +30,12 @@ users: shell: /bin/bash lock_passwd: true ssh_authorized_keys: - - "{{ lookup('file', SSH_keys.public) }}" + - "{{ lookup('file', SSH_keys.public) | string }}" write_files: - path: /etc/ssh/sshd_config content: | -{{ lookup('template', 'files/cloud-init/sshd_config') | indent(width=6, first=True) }} +{{ lookup('template', 'files/cloud-init/sshd_config') | string | indent(width=6, first=True) }} runcmd: - set -x From 8952761c46241fbba310645d7c13de6db80a29db Mon Sep 17 00:00:00 2001 From: Florian Kinder Date: Sat, 8 Nov 2025 10:20:18 +0100 Subject: [PATCH 3/3] Use two-step fact assignment for Vultr startup script Changed to set the cloud-init script as a fact first, then reference that fact in the startup_script module. This follows the pattern used by the Linode provider and avoids JSON serialization issues with nested template lookups. This approach ensures the template is fully evaluated and stored as a string before being passed to the vultr.cloud.startup_script module, which then base64-encodes it for the API. Related to: JSON serialization with "tagless" profile in Ansible 2.19+ --- roles/cloud-vultr/tasks/main.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/cloud-vultr/tasks/main.yml b/roles/cloud-vultr/tasks/main.yml index 2833abd56..c49bb6b5d 100644 --- a/roles/cloud-vultr/tasks/main.yml +++ b/roles/cloud-vultr/tasks/main.yml @@ -3,6 +3,10 @@ import_tasks: prompts.yml - block: + - name: Set cloud-init script as fact + set_fact: + algo_cloud_init_script: "{{ lookup('template', 'files/cloud-init/base.yml') }}" + - name: Creating a firewall group vultr.cloud.firewall_group: name: "{{ algo_server_name }}" @@ -28,7 +32,7 @@ - name: Upload the startup script vultr.cloud.startup_script: name: algo-startup - script: "{{ lookup('template', 'files/cloud-init/base.yml') | string }}" + script: "{{ algo_cloud_init_script }}" - name: Creating a server vultr.cloud.instance: