Skip to content

vm-repair: remove unused opencensus dependency, and declare applicationinsights - #10249

Merged
Julie Zhu (yanzhudd) merged 2 commits into
Azure:mainfrom
EdwinBernal1:vmrepair/fix-854928087-python314-install
Aug 25, 2026
Merged

Julie Zhu (yanzhudd) merged 2 commits into
Azure:mainfrom
EdwinBernal1:vmrepair/fix-854928087-python314-install

Conversation

@EdwinBernal1

@EdwinBernal1 Edwin Bernal Microsoft (EdwinBernal1) commented Aug 25, 2026 •

Copy link
Copy Markdown
Member

🤖 PR Validation — ️✔️ All clear

Breaking Changes
️✔️ None

Related command

az vm repair (all commands) — extension install/upgrade path.

Fixes the install failure reported in ICM 854928087: az extension add --name vm-repair fails with Pip failed with status code 2 on 32-bit Windows installations of the Azure CLI.


Summary

src/vm-repair/setup.py had its dependency declarations inverted:

  1. opencensus was declared but never imported. It appears in no import statement anywhere in azext_vm_repair. Because extensions are installed with pip install --target <extension dir> — fully isolated from the CLI's own site-packages — that dead declaration vendored roughly 20 packages into the extension folder:

    vm-repair -> opencensus -> google-api-core -> google-auth -> cryptography
    

    plus protobuf, cffi, proto-plus, googleapis-common-protos, requests, urllib3, certifi, idna, charset-normalizer, pyasn1, pyasn1-modules, pycparser, six, opencensus-context.

    cryptography stopped publishing 32-bit Windows wheels at version 49.0.0 (48.0.1 was the last with win32 wheels):

    Version win32 wheels win_amd64 wheels Uploaded
    48.0.1 3 4 2026-06-09
    49.0.0 0 4 2026-06-12
    50.0.0 0 4 2026-07-31

    On 32-bit Windows pip finds no compatible wheel, falls back to the sdist, and the source build requires a Rust toolchain — producing the reported Pip failed with status code 2.

  2. applicationinsights was imported but never declared. azext_vm_repair/telemetry.py does from applicationinsights import TelemetryClient, and command_helper_class.py imports telemetry at module scope, so it is on the hot path of every command. It resolved only because the Azure CLI happens to ship applicationinsights 0.11.9 — pip show applicationinsights reports Required-by: as empty, meaning no Azure CLI package requires it. A future CLI that dropped it would break every az vm repair command at import time.

Changes

# Only declare packages that azure-cli-core does not already guarantee; extensions are
# pip-installed with --target, so every entry here is vendored into the extension folder.
# 'requests' is intentionally omitted: azure-cli-core pulls it in via msal/msrest.
DEPENDENCIES = ['applicationinsights~=0.11.9']
  • src/vm-repair/setup.py — drop opencensus, declare applicationinsights, bump VERSION 2.2.5 → 2.2.6.
  • src/vm-repair/HISTORY.rst — 2.2.6 changelog entry in user-facing language.
  • src/vm-repair/azext_vm_repair/tests/latest/test_dependency_declarations.py — new static AST regression test.

applicationinsights 0.11.10 is a zero-dependency py2.py3-none-any wheel, so this removes ~20 vendored packages and adds one small universal one.

requests is deliberately left undeclared. It is imported by shipped code, but it is guaranteed by the CLI dependency graph (Required-by: msal, msrest, PyGithub, requests-oauthlib). Vendoring it into the extension folder would risk shadowing the CLI's own requests on sys.path. The reasoning is recorded in a code comment so it is not "corrected" later.

Regression test

The new test asserts both directions of the invariant, so this class of defect cannot silently return:

  • every third-party import is declared → catches the missing applicationinsights
  • every declared dependency is imported → catches the dead opencensus

Verified it actually bites: forcing the declared set back to {'opencensus'} fails both assertions (['applicationinsights'] != [] and ['opencensus'] != []).

Testing

All gates run locally in a proper azdev environment (azdev 0.2.13, Python 3.13.15 x64):

  • azdev style vm-repair → PASSED (pylint PASSED, flake8 PASSED)
  • azdev linter vm-repair → PASSED (no violations; custom pylint rules also clean)
  • azdev test vm-repair → 96 passed, 35 skipped in 12.55s (skips are the live-Azure scenarios)
  • python scripts/ci/test_index.py -q → 9 tests, OK (2 skipped)
  • 32-bit repro on real win32 Python 3.14.7 → old dependency fails, new dependency succeeds (details below)

The two new regression tests are collected and pass as part of the azdev run:

test_dependency_declarations.py::DependencyDeclarationTests::test_every_third_party_import_is_declared PASSED
test_dependency_declarations.py::DependencyDeclarationTests::test_no_declared_dependency_is_unused    PASSED

32-bit reproduction (confirmed)

Reproduced on a real 32-bit Python 3.14.7 (sysconfig.get_platform() == 'win32', struct.calcsize('P')*8 == 32), using the same install shape the CLI uses — pip install --target, no wheel-only restriction:

Before (old dependency) — fails:

> python.exe -m pip install --target <dir> "opencensus~=0.11.4" --no-cache-dir

  $HOST   = i686-pc-windows-msvc
  $TARGET = i686-pc-windows-msvc
  openssl-sys = 0.9.117
  It looks like you're compiling for MSVC but we couldn't detect an OpenSSL installation.
  maturin failed: Cargo build finished with "exit code: 101"
ERROR: Failed building wheel for cryptography
Failed to build cryptography

pip selects a cryptography release with no win32 wheel, falls back to the sdist, and attempts a Rust/OpenSSL source build for i686-pc-windows-msvc.

After (new dependency) — succeeds:

> python.exe -m pip install --target <dir> "applicationinsights~=0.11.9" --no-cache-dir

Downloading applicationinsights-0.11.10-py2.py3-none-any.whl (55 kB)
Successfully installed applicationinsights-0.11.10
exit=0

Vendored contents afterwards are just applicationinsights/ and its .dist-info — no cryptography, cffi, google-*, protobuf, or opencensus. Zero native code.

Note

Two honest caveats on this repro. It used a standalone 32-bit CPython rather than a 32-bit Azure CLI, because no 32-bit CLI was installable here; the failing component is pip's resolver, which is what was exercised. And pip returned exit code 1 here versus the 2 in the incident report — the failure mode is identical (cryptography source build), and the numeric code varies by pip version.

Also worth recording: resolving the same tree with pip download --only-binary=:all: --platform win32 succeeds, because that flag forces pip to backtrack to cryptography 48.0.1 (the last release with win32 wheels). That flag is not used by az extension add, so it masks the bug — a wheel-only check is not a valid test for this issue.

Positive control also captured: an isolated 64-bit install of 2.2.5 (fresh AZURE_CONFIG_DIR) succeeded and its debug log shows the full opencensus tree — including cryptography — being vendored.

Version & changelog

  • setup.py VERSION: 2.2.5 → 2.2.6
  • HISTORY.rst entry added: yes

Cross-repo impact (repair-script-library)

None. No --run-id, map.json, or script changes.

Security review

Reduces supply-chain surface by removing ~20 unnecessary vendored packages. No untrusted-input → shell paths touched; no credential handling or logging changed.

Backward compatibility

No command, parameter, default, or behavior changes. Patch-level and backward compatible.

Note on the original triage

The ICM was initially attributed to pkgutil.get_loader() under Python 3.14, with a recommendation to publish 2.2.5. vm-repair 2.2.5 was in fact already published on 2026-08-20 (before the ICM was filed), and pkgutil is runtime code that cannot cause pip to exit 2 during install. The reporter's own 64-bit run installed 2.2.5 from the same index at the same time the 32-bit run failed — the differentiator was architecture, not the index. This change addresses the actual install-time cause.


General Guidelines

  • Have you run azdev style <YOUR_EXT> locally? — passed, as did azdev linter vm-repair and azdev test vm-repair
  • Have you run python scripts/ci/test_index.py -q locally? — passes
  • My extension version conforms to the Extension version schema — patch bump, no surface change

About Extension Publish

src/index.json is intentionally not modified in this PR.

…sights

opencensus was declared in setup.py but never imported anywhere in the
extension. Because extensions install with `pip --target`, that dead
declaration vendored ~20 packages into the extension folder, including
cryptography, which stopped publishing 32-bit Windows wheels in 49.0.0. On a
32-bit CLI pip found no compatible wheel, fell back to the sdist, and failed
with `Pip failed with status code 2` (ICM 854928087).

applicationinsights is imported by telemetry.py on the hot path of every
command but was never declared; it resolved only because the Azure CLI happens
to ship it, and no Azure CLI package requires it. requests stays undeclared on
purpose: azure-cli-core guarantees it via msal/msrest, and vendoring it could
shadow the CLI's own copy on sys.path.

Adds a static regression test asserting both directions of the invariant: no
undeclared third-party import, and no declared-but-unused dependency.
Copilot AI lite review requested due to automatic review settings August 25, 2026 05:27
@azure-client-tools-bot-prd

Copy link
Copy Markdown

Hi Edwin Bernal Microsoft (@EdwinBernal1),
Please write the description of changes which can be perceived by customers into HISTORY.rst.
If you want to release a new extension version, please update the version in pyproject.toml (or setup.py, if the extension has not migrated yet) as well.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates vm-repair dependency metadata to prevent 32-bit Windows installation failures and ensure telemetry dependencies are declared.

Changes:

  • Replaces unused opencensus with applicationinsights.
  • Bumps version to 2.2.6 and adds release notes.
  • Adds dependency declaration regression tests.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Summary
src/vm-repair/setup.py Updates dependencies and version.
src/vm-repair/HISTORY.rst Documents the 2.2.6 fix.
src/vm-repair/azext_vm_repair/tests/latest/test_dependency_declarations.py Adds import/dependency checks; currently uses sys.stdlib_module_names, which is unavailable on supported Python 3.9.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

sys.stdlib_module_names was added in 3.10, but setup.py still advertises
Python 3.9. On a 3.9 run _third_party_imports() raised AttributeError before
reaching either assertion, so the regression test failed rather than testing.

Falls back to deriving the stdlib set from sys.builtin_module_names plus the
stdlib, lib-dynload and DLLs directories when the attribute is absent, so the
test keeps its coverage on 3.9 instead of being skipped there.

Verified by forcing the fallback path on 3.13: both branches classify the
extension's imports identically (only applicationinsights is third-party), and
no stdlib module the extension imports is missed by the fallback.
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

@yanzhudd
Julie Zhu (yanzhudd) merged commit 8312565 into Azure:main Aug 25, 2026
24 checks passed
@azclibot

Copy link
Copy Markdown
Collaborator

[Release] Update index.json for extension [ vm-repair-2.2.6 ] : https://dev.azure.com/msazure/One/_build/results?buildId=178212921&view=results

yaotongms pushed a commit to yaotongms/azure-cli-extensions that referenced this pull request Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants