Repository: rancher/cluster-api-provider-rke2 (go)

Issue:
additionalUserData.data renders invalid cloud-config
**What happened:**
When using the additionalUserData.data in cloud-config format to pass cloud-init actions to an ubuntu server, cloud-init fails to run because  of the formatting

```
	failed to unmarshal arbitrary cloud-init data: yaml: line 2: block sequence entries are not allowed in this context, please check if you put valid yaml data:
	users: - name: ubuntu
	  ssh_authorized_keys:
	    - ssh-rsa ...
```

**What did you expect to happen:**

The output should be in the correct yaml format:
```
	users: 
          - name: ubuntu
	     ssh_authorized_keys:
	     - ssh-rsa ....
```


**How to reproduce it:**

``` 
apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
kind: RKE2ControlPlane
  metadata:
    name: management-cluster-control-plane
    namespace: default
  spec:
    agentConfig:
    format: cloud-config
    additionalUserData:
      data:
        users: |
          - name: ubuntu
            ssh_authorized_keys:
              - ssh-rsa ...
```


**Anything else you would like to add:**
[Miscellaneous information that will assist in solving the issue.]

There was a similar issue #212 but it was closed so maybe I'm just doing it incorrectly, is there a working example that you can share?

**Environment:**
K3s: v1.31.2+k3s1
clusterctl --core "cluster-api:v1.8.5" --infrastructure "metal3:v1.8.3" --bootstrap "rke2:v0.9.0" --control-plane "rke2:v0.9.0"
- rke provider version: rke2:v0.9.0
- OS (e.g. from `/etc/os-release`): Ubuntu 22.04 LTS


Pull request:
:bug: Format additionalUserData maps and lists to ensure correct YAML output
<!--
Label the PR with the kind of change this for:

kind/feature
kind/bug
kind/documentation
kind/regression
kind/*
-->

**What this PR does / why we need it**:

Adds `additionalUserData.data` content formatting, according to bootstrap cloud-init template indentation.

This change eliminates the need to specify complex values as JSON, such as:
- `{'ephemeral0': '/dev/vdb'}` for maps
- `['data']` for lists

<!-- Enter a description of the change and why this change is needed -->

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #527

**Special notes for your reviewer**:

**Checklist**:
<!-- Put an "X" character inside the brackets of each completed task. Some may be optional depending on the PR in which case these can be deleted -->

- [ ] squashed commits into logical changes
- [ ] includes documentation
- [x] adds unit tests
- [ ] adds or updates e2e tests


Patch:
diff --git a/bootstrap/internal/cloudinit/cloudinit.go b/bootstrap/internal/cloudinit/cloudinit.go
index 9586325..87a71c1 100644
--- a/bootstrap/internal/cloudinit/cloudinit.go
+++ b/bootstrap/internal/cloudinit/cloudinit.go
@@ -183,6 +183,36 @@ func cleanupArbitraryData(arbitraryData map[string]string) error {
 
 	m := make(map[string]interface{})
 
+	// Make individual corrections to each value
+	for k, v := range arbitraryData {
+		b := bytes.Buffer{}
+		en := yaml.NewEncoder(&b)
+		en.SetIndent(defaultYamlIndent)
+
+		mapping := map[string]interface{}{}
+		if err := yaml.Unmarshal([]byte(v), &mapping); err == nil {
+			if err := en.Encode(&mapping); err != nil {
+				return fmt.Errorf("invalid map value provided: '%s', error: %w", v, err)
+			}
+
+			ident := "\n  "
+			arbitraryData[k] = ident + strings.ReplaceAll(b.String(), "\n", ident)
+
+			continue
+		}
+
+		list := []interface{}{}
+		if err := yaml.Unmarshal([]byte(v), &list); err == nil {
+			if err := en.Encode(&list); err != nil {
+				return fmt.Errorf("invalid list value provided: '%s', error: %w", v, err)
+			}
+
+			arbitraryData[k] = fmt.Sprintf("\n%s", b.String())
+
+			continue
+		}
+	}
+
 	kind := "arbitrary_prepare"
 	tm := template.New(kind).Funcs(defaultTemplateFuncMap)
 


Test patch:
diff --git a/bootstrap/internal/cloudinit/cloudinit_test.go b/bootstrap/internal/cloudinit/cloudinit_test.go
index acdc08a..3514c0e 100644
--- a/bootstrap/internal/cloudinit/cloudinit_test.go
+++ b/bootstrap/internal/cloudinit/cloudinit_test.go
@@ -254,14 +254,15 @@ runcmd:
   - 'print hello world' 
 `
 		arbitraryData = map[string]string{
-			"disk_setup": `
-  ephemeral0:
-    table_type: mbr
-    layout: False
-    overwrite: False`,
+			"disk_setup": `ephemeral0:
+  table_type: mbr
+  layout: False
+  overwrite: False`,
 			"device_aliases": "{'ephemeral0': '/dev/vdb'}",
-			"runcmd": `
-  - 'print hello world'`,
+			"runcmd":         `- 'print hello world'`,
+			"users": `- name: capv
+  sudo: ALL=(ALL) NOPASSWD:ALL`,
+			"list": "['data']",
 		}
 	})
 
@@ -287,12 +288,22 @@ write_files:
       
 
 
-device_aliases: {'ephemeral0': '/dev/vdb'}
+device_aliases: 
+  ephemeral0: /dev/vdb
+  
 disk_setup: 
   ephemeral0:
+    layout: false
+    overwrite: false
     table_type: mbr
-    layout: False
-    overwrite: False
+  
+list: 
+- data
+
+users: 
+- name: capv
+  sudo: ALL=(ALL) NOPASSWD:ALL
+
 runcmd:
   - 'curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=v1.25.6+rke2r1 INSTALL_RKE2_TYPE="agent" sh -s -'
   - '/opt/rke2-cis-script.sh'