Skip to content

fix(nginx_k8s): close file handles returned by container.pull#492

Open
tonyandrewmeyer wants to merge 3 commits into
canonical:mainfrom
tonyandrewmeyer:fix-nginx-k8s-close-pull-handles
Open

fix(nginx_k8s): close file handles returned by container.pull#492
tonyandrewmeyer wants to merge 3 commits into
canonical:mainfrom
tonyandrewmeyer:fix-nginx-k8s-close-pull-handles

Conversation

@tonyandrewmeyer

Copy link
Copy Markdown
Contributor

Summary

  • Container.pull() returns a real local file handle — under real pebble it's open() on a tempfile.NamedTemporaryFile, under ops.testing it's open() on the mounted path. Letting it fall out of scope without .close() emits ResourceWarning (and leaks a file descriptor until GC runs).
  • Wrap the four cert/config reads in _nginx.py and _tls_config.py in with blocks, factor the repeated pull-if-exists pattern into a small _read_if_exists helper in each module.
  • Add tests/unit/test_no_resource_leaks.py with two regression tests that capture ResourceWarning via warnings.catch_warnings(record=True) and assert no unclosed file warning is emitted. Each test was verified to fail with AssertionError: unclosed file <...> if the corresponding fix is reverted.

Note on the test design: the tests filter captured warnings by the 'unclosed file' substring and rely on CPython's refcount-based collection (no explicit gc.collect()), so unrelated upstream leaks (e.g. a known one in scenario.Context) won't false-positive these tests.

Test plan

  • just unit nginx_k8s — 59/59 passing, including the two new regression tests.
  • Reverting _nginx.py alone makes test_has_config_changed_closes_pull_handle fail with unclosed file <…/nginx.conf…>.
  • Reverting _tls_config.py alone makes test_sync_certificates_closes_pull_handles fail with unclosed file <…/server.cert…>.

🤖 Generated with Claude Code

tonyandrewmeyer and others added 2 commits May 26, 2026 01:33
container.pull() returns a real local file handle: ops streams the
remote file's bytes into a tempfile and returns open() on it, so
leaving the handle to be GC'd raises a ResourceWarning. Use a context
manager and factor the cert-read pattern into _read_if_exists so the
module is clean under -Werror.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TLSConfigManager._sync_certificates had the same `pull(...).read()` anti-
pattern as Nginx._configure_tls — three more unclosed file handles. Factor
the same `_read_if_exists` helper into _tls_config.py and add regression
tests under tests/unit/test_no_resource_leaks.py that capture
ResourceWarning via `catch_warnings(record=True)` for both the cert-read
and nginx-config-read paths. Each test fails with the message
"AssertionError: unclosed file ..." if the corresponding fix is reverted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tonyandrewmeyer tonyandrewmeyer requested a review from a team as a code owner May 26, 2026 00:24
Comment thread nginx_k8s/tests/unit/test_no_resource_leaks.py Outdated
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.

1 participant