Skip to content

fix: recover from corrupted network-config.json cache - #7079

Open
pujitha24 wants to merge 1 commit into
canonical:mainfrom
pujitha24:auto/issue-7069
Open

fix: recover from corrupted network-config.json cache#7079
pujitha24 wants to merge 1 commit into
canonical:mainfrom
pujitha24:auto/issue-7069

Conversation

@pujitha24

Copy link
Copy Markdown

Proposed Commit Message

fix: recover from corrupted network-config.json cache

Init._write_network_config_json() read the cached
network-config.json instance file via util.load_json() with no
exception handling. A corrupted, empty, or truncated cache file
(e.g. from an interrupted write) makes json.loads() raise
JSONDecodeError, or makes util.load_json()'s root-type check raise
TypeError when the parsed value isn't a dict. Either exception was
unhandled and propagated out of _write_network_config_json(), which
is called from apply_network_config() during boot, so a bad cache
file broke network configuration entirely instead of being safely
regenerated.

Wrap the load in a try/except covering JSONDecodeError, TypeError,
and ValueError, matching the existing pattern used for the same
util.load_json() call a few lines below in this file. On failure,
log a warning and treat the cache as absent so the current
network config is written out fresh, mirroring the no-cache-file
code path just below.

Refs GH-7069

Additional Context

The root cause and fix were suggested in the issue itself. This PR
additionally catches TypeError (not just JSONDecodeError/
ValueError), since util.load_json() raises TypeError when the
cached file contains syntactically valid JSON that isn't a dict
(e.g. a truncated write leaving null or a list) -- the same
exception class already handled for an equivalent util.load_json()
call a few lines below in cloudinit/stages.py (system_info/features
cache) and in cloudinit/sources/DataSourceVMware.py.

Test Steps

Ran the affected test module directly:

python -m pytest tests/unittests/test_stages.py -q

60 passed.

The new test
test_write_network_config_json_recovers_from_corrupted_cache is
parametrized over three corrupted-cache shapes (malformed JSON, an
empty file, and valid JSON of the wrong type) and asserts that
_write_network_config_json logs a warning and rewrites the cache
instead of raising. I confirmed this test fails with an unhandled
json.decoder.JSONDecodeError against the pre-fix code and passes
after the fix.

Also ran black --check, isort --check-only, ruff check,
pylint --disable=all --enable=E, and mypy against the two
changed files (cloudinit/stages.py,
tests/unittests/test_stages.py); all clean.

This change was validated with local unit tests and static checks
only (no live/dev-stack boot was performed), since the defect is a
straightforward unhandled-exception bug reproducible with a targeted
unit test.

Merge type

  • Squash merge using "Proposed Commit Message"
  • Rebase and merge unique commits. Requires commit messages per-commit each referencing the pull request number (#<PR_NUM>)

Fixes #7069

Init._write_network_config_json() read the cached
network-config.json instance file via util.load_json() with no
exception handling. A corrupted, empty, or truncated cache file
(e.g. from an interrupted write) makes json.loads() raise
JSONDecodeError, or makes util.load_json()'s root-type check raise
TypeError when the parsed value isn't a dict. Either exception was
unhandled and propagated out of _write_network_config_json(), which
is called from apply_network_config() during boot, so a bad cache
file broke network configuration entirely instead of being safely
regenerated.

Wrap the load in a try/except covering JSONDecodeError, TypeError,
and ValueError, matching the existing pattern used for the same
util.load_json() call a few lines below in this file. On failure,
log a warning and treat the cache as absent so the current
network config is written out fresh, mirroring the no-cache-file
code path just below.

Validation: added
test_write_network_config_json_recovers_from_corrupted_cache to
tests/unittests/test_stages.py, parametrized over malformed JSON,
an empty file, and syntactically valid JSON of the wrong type
(e.g. a list). Confirmed the new test fails with an unhandled
JSONDecodeError on the pre-fix code and passes after the fix.
Ran `python -m pytest tests/unittests/test_stages.py -q`: 60
passed. Also ran black, isort, ruff, `pylint -E`, and mypy on the
changed files; all clean.

Report: canonical#7069
Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
Assisted-by: claude-sonnet-5 (via Claude Code)
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.

Should be wrapped in try...except in case of JSONDecodeError

1 participant