Skip to content

Conversation

@levkropp
Copy link
Contributor

fixes #4176

This pull request refactors the emit_yaml function in src/utils/yaml_node_utils.cpp to handle YAML nodes recursively, allowing for the addition of special handling, which is needed to properly handle scalar strings that resemble octal numbers.

Enhancements to YAML node handling:

  • Refactored std::string mp::utils::emit_yaml(const YAML::Node& node) to introduce a recursive helper function (emit_node) for processing YAML nodes. This allows the function to handle Map, Sequence, and scalar nodes more robustly.
  • Added special handling for scalar strings that look like octal numbers (e.g., "0755") by tagging them with YAML::LocalTag("str") to preserve their string representation in the emitted YAML.

These changes seem necessary due to how yaml-cpp handles re-emission of YAML input. If the YAML input uses quotes ("0755"), the YAML spec says this is a string and should remain a string, however it appears that yaml-cpp is seeing a scalar "0755", and then writing it out in a way that causes it to be emitted as a number. These changes should not affect anything with regards to YAML parsing other than this particular case where a cloud-init file has a write_files section with a permissions string defined.

@levkropp levkropp force-pushed the yaml-cloudinit-octal-parsing branch from d0dc7e7 to 5437847 Compare June 23, 2025 13:59
@levkropp levkropp force-pushed the yaml-cloudinit-octal-parsing branch from 5437847 to 8dfbad1 Compare June 23, 2025 14:14
@codecov
Copy link

codecov bot commented Jun 23, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.33%. Comparing base (47f57a0) to head (35809ad).
⚠️ Report is 495 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4177      +/-   ##
==========================================
+ Coverage   89.31%   89.33%   +0.01%     
==========================================
  Files         259      259              
  Lines       15684    15711      +27     
==========================================
+ Hits        14008    14035      +27     
  Misses       1676     1676              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@levkropp
Copy link
Contributor Author

levkropp commented Jul 7, 2025

I have confirmed that:

  • Our personal fork's changes to yaml-cpp are not responsible for these issues with processing permissions octals
  • The latest upstream of yaml-cpp still has these issues with octal scalars
  • We can implement our existing necessary fixes to colons directly into emit_yaml and no longer need to use our own fork of yaml_cpp (our fork's changes only is necessary for strings with spaces after colons (e.g. key: value) which we can indeed handle in emit_yaml)

HOWEVER: I am getting issues with timeouts, even though the cloud-init configuration completes successfully. For some reason on the latest yaml-cpp there are issues on the SSH or gRPC level regarding communication. The multipass exec command we run to check if a cloud-init config succeeded works when run manually, but it never gets called

@levkropp levkropp force-pushed the yaml-cloudinit-octal-parsing branch from 8ebfd65 to 8dfbad1 Compare July 7, 2025 15:21
@levkropp
Copy link
Contributor Author

levkropp commented Jul 7, 2025

Because of the issues I have been seeing with updating to the latest upstream of yaml-cpp, I have reverted the PR back to the single commit which implements the fix for #4176 , and have created a new branch to deal with investigations into what is necessary to make everything work without the fork's changes. I will create a separate PR to deal with updating yaml-cpp to upstream.

~/yaml-cloudinit-octal-parsing/build$ ./bin/multipass launch --name cdo --cpus 4 --memory 8G --disk 50G --cloud-init https://raw.githubusercontent.com/canonical/multipass/refs/heads/main/data/cloud-init-yaml/cloud-init-charm-dev.yaml
Launched: cdo
~/yaml-cloudinit-octal-parsing/build$ ./bin/multipass shell cdo
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-60-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Mon Jul  7 11:31:25 EDT 2025

  System load:  0.22              Processes:             133
  Usage of /:   3.8% of 47.39GB   Users logged in:       0
  Memory usage: 3%                IPv4 address for ens3: 10.44.19.6
  Swap usage:   0%


Expanded Security Maintenance for Applications is not enabled.

85 updates can be applied immediately.
65 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

ubuntu@cdo:~$ sudo cloud-init schema --system
Found cloud-config data types: user-data, vendor-data, network-config

1. user-data at /var/lib/cloud/instances/cdo/cloud-config.txt:
  Valid schema user-data

2. vendor-data at /var/lib/cloud/instances/cdo/vendor-cloud-config.txt:
Cloud config schema deprecations: system_info:  Deprecated in version 24.2. System and/or distro specific settings. This is not intended to be overridden by user data or vendor data.
  Valid schema vendor-data

3. network-config at /var/lib/cloud/instances/cdo/network-config.json:
  Valid schema network-config
ubuntu@cdo:~$ 

@levkropp levkropp marked this pull request as ready for review July 7, 2025 15:34
@levkropp levkropp requested a review from xmkg July 8, 2025 16:01
// Special handling for strings that look like octal numbers (e.g. "0755")
if (n.IsScalar())
{
std::string value = n.Scalar();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::string value = n.Scalar();
const std::string value = n.Scalar();

Comment on lines 101 to 104
else
{
emitter << n;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
else
{
emitter << n;
}

Comment on lines 106 to 109
else
{
emitter << n;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
else
{
emitter << n;
}
emitter << n;

Copy link
Member

@xmkg xmkg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@levkropp levkropp requested a review from Sploder12 July 9, 2025 15:36
Copy link
Contributor

@Sploder12 Sploder12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@levkropp levkropp added this pull request to the merge queue Jul 9, 2025
Merged via the queue into main with commit fa0f993 Jul 9, 2025
23 checks passed
@levkropp levkropp deleted the yaml-cloudinit-octal-parsing branch July 9, 2025 17:43
github-merge-queue bot pushed a commit that referenced this pull request Jul 11, 2025
This pull request involves updating the URL of the `yaml-cpp` submodule
from our fork's URL to the upstream URL. We implement our fork's changes
(double-quoting all strings with a colon `:`) by adding a condition to
the recursive YAML emission handling structure introduced in #4177

Launching instances has not been affected, and there has not been a
regression introduced in launching instances with cloud-init YAML files.
github-merge-queue bot pushed a commit that referenced this pull request Jul 11, 2025
This pull request involves updating the URL of the `yaml-cpp` submodule
from our fork's URL to the upstream URL. We implement our fork's changes
(double-quoting all strings with a colon `:`) by adding a condition to
the recursive YAML emission handling structure introduced in #4177

Launching instances has not been affected, and there has not been a
regression introduced in launching instances with cloud-init YAML files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloud-init permissions field type incorrectly parsed as integer (e.g., 0755 → 493)

3 participants