canonical / cloud-init

Official upstream for the cloud-init: cloud instance initialization
https://cloud-init.io/
Other
2.87k stars 856 forks source link

[enhancement]: Query for schema failures #5100

Open Chris-Peterson444 opened 5 months ago

Chris-Peterson444 commented 5 months ago

Enhancement

It would be really great if there was a dedicated method to query cloud-init for schema validation errors, particularly in a machine readable format such as the json format option for cloud-init status. At minimum, I am interested in top-level keys that failed to validate and only their names. Although I'm sure there's some uses for further information I haven't thought of yet!

Use case example

In Subiquity, new users may confuse cloud-config with autoinstall and provide autoinstall directives in cloud-config mistakenly. This means the directives never make it to Subiquity and the behavior does not match their expectation. To avoid this silent failure, we query cloud-init for schema validation errors and halt the install if a recognized autoinstall directive was the cause of a cloud-init schema failure.

The current method for this is to:

  1. Read the output of cloud-init status --format=json and look for the line "Invalid cloud-config provided: Please run 'sudo cloud-init schema --system' to see the schema errors." in the recoverable_errors section.
  2. Use regex to match the "Additional properties are now allowed ('key1', 'key2', ... , 'keyN' were unexpected)" line printed to stderr by said command and parse out the key names.

This implementation is fragile to output format changes and requires coordinating multiple calls to cloud-init. If instead we could make one call to (for example) cloud-init schema --system --format=json and get a response that lists all of the unrecognized keys, has per-key validation error information, or some other format that would allow parsing the key-names reliably, it would help a lot!

blackboxsw commented 5 months ago

This is a good suggestion @Chris-Peterson444 and I think we should look to support this in machine-readable output from cloud-init schema subcommand. As you said, parsing cloud-init schema --system output or cloud-init status output is fragile at best.

In the meantime before we are able to implement a machine-readable cloud-init schema --system --format=json one might be able to invoke the following in python if you really only care about user-data at the moment. (schema --system happens to look at user-data, vendor-data and network-config instance-data types which may be more than you want right now).

from cloudinit.conifg.schema import get_schema

# probably need a preflight check to ensure cloud-init isn't disabled first 
full_schema = get_schema()
paths = read_cfg_paths(fetch_existing_datasource="trust")
userdata_file = paths.get_ipath("cloud_config)
if os.file.exists(userdata_file):
    validate_cloudconfig_file(userdata_file), schema=full_schema)
Chris-Peterson444 commented 5 months ago

Thanks for the suggestion! I think we mostly care about user-data, but I'll have to double check that.