Comment 7 for bug 1983306

Revision history for this message
Chad Smith (chad.smith) wrote :

This makes sense. I think we can minimally fix the messaging seen on the commandline when running `sudo cloud-init schema --system` to actually have it consume the rendered #cloud-config or #template: jinja user-data instead of the raw `#include <your-url>` as the potential source for invalid user-data.

Minimally I think we need to fix https://github.com/canoncloud-config ical/cloud-init/blob/main/cloudinit/config/schema.py#L621-L623 to validated the processed/rendered userdata instead of "userdata_raw" so that `sudo cloud-init schema --system` provides a concise error about what the procesed invalid user-data is.

I can validate that we get a less than desirable message from `sudo cloud-init schema --system` when we launch a container with a valid #include containing valid #cloud-config.

reproducer:
# terminal 1 on host system 192.168.1.8
$ mkdir -p instance-data
$ cd instance-data
$ cat > user-data <<EOF
#cloud-config
ssh_import_id: [chad.smith]
EOF

$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

# terminal 2 on host system 192.168.1.8
$ cat > include.yaml <<EOF
#include http://192.168.1.8:8000/user-data
EOF
$ lxc launch ubuntu-daily:kinetic include-k -c user.user-data="$(cat include.yaml)"

$ lxc exec include-k bash
root@include-k:~#

# See raw userdata (this is ok/desired)
root@include-k:~# cloud-init query userdata
#include http://192.168.1.8:8000/user-data

# verify cloud-init schema --system alias for rendered user-data (not correct)
root@include-k:~# cloud-init schema --system --annotate
#include http://192.168.1.8:8000/user-data # E1
# Errors: -------------
# E1: File None needs to begin with "#cloud-config"

What I think we want:
root@include-k:~# cloud-init schema --system --annotate
Valid cloud-config: system userdata

This comes with something like the following diff, but needs tweaking and unittest coverage
diff --git a/cloudinit/config/schema.py b/cloudinit/config/schema.py
index d62073d0..aa4ec3a1 100644
--- a/cloudinit/config/schema.py
+++ b/cloudinit/config/schema.py
@@ -18,8 +17,8 @@ from typing import TYPE_CHECKING, List, NamedTuple, Optional, Type, Union, cast
 import yaml

 from cloudinit import importer, safeyaml
-from cloudinit.cmd.devel import read_cfg_paths
-from cloudinit.util import error, get_modules_from_dir, load_file
+from cloudinit.stages import Init
+from cloudinit.util import encode_text, error, get_modules_from_dir, load_file

 try:
     from jsonschema import ValidationError as _ValidationError
@@ -617,9 +616,17 @@ def validate_cloudconfig_file(config_path, schema, annotate=False):
                 "Unable to read system userdata as non-root user."
                 " Try using sudo"
             )
- paths = read_cfg_paths()
- user_data_file = paths.get_ipath_cur("userdata_raw")
- content = load_file(user_data_file, decode=False)
+ init = Init(ds_deps=[])
+ ds = init.fetch("trust")
+ ud = ds.get_userdata()
+ content = None
+ for part in ud.walk():
+ if part.get_content_type() == "text/cloud-config":
+ content = encode_text(part.get_payload())
+ break
+ if not content:
+ print("No cloud-config userdata found. Skipping verification")
+ return
     else:
         if not os.path.exists(config_path):
             raise RuntimeError(