Skip to content

Azure IPAM v4.0.0 Release #377

Open
DCMattyG wants to merge 169 commits into
mainfrom
ipam-3.7.0
Open

Azure IPAM v4.0.0 Release #377
DCMattyG wants to merge 169 commits into
mainfrom
ipam-3.7.0

Conversation

@DCMattyG
Copy link
Copy Markdown
Contributor

@DCMattyG DCMattyG commented Mar 11, 2026

Azure IPAM v4.0.0

This is a major release that delivers significant framework upgrades, a data grid migration, authentication modernization, comprehensive documentation overhaul, revamped examples, and numerous bug fixes.


Major Framework & Dependency Upgrades

  • React 18 → 19: Full migration including removal of forwardRef wrappers (ref-as-prop), removal of PropTypes, explicit null for useRef() calls, and migration of LoadingButton to Button
  • MSAL v4 → v5 (@azure/msal-browser 4.x → 5.x, @azure/msal-react 3.x → 5.x): Removed obsolete config, consolidated event types, fixed silent token timeout recovery (timed_out error code), and prevented iframe fallback timeout loops
  • Inovua React Data Grid → AG Grid (ag-grid-community / ag-grid-react 35.x): Complete migration to AG Grid including centralized DataGrid component, custom styling, column state persistence, unified data loading overlays, and custom cell renderers (drill-down, info, progress)
  • Vite 7 → 8 (vite 7.x → 8.x, @vitejs/plugin-react 5.x → 6.x): Migrated to Vite 8 which replaces Rollup with Rolldown and esbuild with Oxc for bundling, transforms, and minification. Removed vite-plugin-eslint2 (redundant with editor-based linting and incompatible with Vite 8)
  • ESLint 10: Upgraded from ESLint 9 to 10 with modern React linting plugins (@eslint-react/eslint-plugin v5, eslint-plugin-react-hooks v7 — which now consolidates the React Compiler lint rules per the React Compiler 1.0 release), replacing eslint-plugin-react. Added dist/ ignore, fixed no-useless-assignment violations, and removed unused eslint-plugin-jest. Resolved all remaining lint warnings as part of the React 19 modernization — useContextuse, <Context.Provider><Context>, ref naming conventions, stable list keys, hoisted static styled components, migration of SnackbarUtils to notistack's standalone enqueueSnackbar, and moved "ref assigned during render" patterns into useEffect
  • MUI v7 → v9 (@mui/material 7.3.x → 9.0.x, @mui/icons-material 7.3.x → 9.0.x): Major two-version jump. Migrated deprecated component props to the unified slots/slotProps API (largely via @mui/codemod), moved deprecated system props into sx, replaced the removed Unstable_Grid2 with the new default Grid (using size={{ xs: N }}), renamed removed Outline (no "d") icon exports to their Outlined counterparts, and removed @mui/lab (no longer needed — LoadingButton's loading prop is now native to Button)
  • Updated NPM packages across the board (Vite 7.3.x, React Router 7.13.x, MUI 7.3.x, etc.)

Engine & Backend

  • Azure Function Blueprints: Implemented Blueprint-based function naming for improved clarity
  • Python dependency cleanup: Removed msal, azure-common, azure-keyvault-secrets, and six; added azure-mgmt-resource-subscriptions to address Azure SDK module separation
  • Python linting: Added pyproject.toml with Ruff linter configuration (pycodestyle, pyflakes, isort). Resolved all lint violations across 18 engine files — bare except clauses, wildcard imports replaced with explicit names, unused imports/variables, invalid escape sequences, import sorting and grouping
  • Reservation logic hardening: Fixed CIDR overlap detection during auto-fulfillment, added validation for all in-block vNet prefix overlap checks, and made auto-fulfillment idempotent by deduping existing block vNet associations
  • Endpoint fix: Standalone NICs are now included in the Endpoint list (fixes Standalone NICs not listed in Endpoint node #371)
  • Network associations fix: Resolved improper handling of missing vNETs and vHUBs (fixes Error fetching available IP Block networks #350)

UI & UX Improvements

  • Drill-down navigation in Discover (fixes Navigation Improvements #183): Added hierarchical drill-down with multi-filter pass-through and hidden column auto-reveal when filters are active
  • Centralized authentication handling: New AuthHandler for MSAL error handling, centralized token acquisition via tokenService
  • Custom DraggablePaper component: Replaced react-draggable package with a purpose-built component
  • Associations UX: Shifted API work to Redux thunks, optimized data refresh, fixed infinite update loops by separating initial grid selection from user selection state
  • Planner data loading: Addressed issue where Planner would not load when data was incomplete (fixes Planner will not load #366)
  • Reservation UX: Fixed view reversion after cancelling a Reservation, fixed column sorting, and streamlined the interface
  • Unified grid experience: Centralized DataGrid and ConfigureGrid components with shared filter utilities, consistent loading overlays, and AG Grid custom styling (brightness filter for row hover)
  • Search bar: Fixed messaging when no resources are found in Azure IPAM scope

Deployment, Build & Infrastructure

  • RHEL images updated to UBI9
  • Dockerfiles optimized: Improved layering, removed unneeded steps across all container images. Resolved Hadolint lint violations (ADDCOPY, JSON notation for CMD/ENTRYPOINT, pipefail for piped RUN commands). Added centralized .hadolint.yaml for rule suppressions
  • KeyVault Soft Delete added to deployment and migration Bicep templates (fixes Enable soft delete for Key Vault #373)
  • Build flexibility: Added support for building with either current or latest NPM/Python packages
  • CI/CD path exclusions: Added exclusions to avoid unnecessary test/build runs for documentation-only changes
  • GitHub Actions modernized: Bumped all workflow actions to their latest versions (checkout@v6, setup-node@v6, setup-python@v6, github-script@v9, create-github-app-token@v3, azure/login@v3, hadolint-action@v3.3.0) to address the Node.js 20 runner deprecation
  • Azure PowerShell SDK v14 compatibility: Fixed Get-AzAccessToken breaking changes (fixes Breaking changes to Get-AzAccessToken #343); updated deploy & migrate scripts

Documentation Overhaul

  • Massively revamped How-To docs: authentication, exclusions, Discover, Reservations, External Networks, and Virtual Network Associations sections
  • New documentation: Comprehensive automation docs, API docs for vNet Associations, initial External Networks docs, detailed Reservations feature docs
  • 50+ screenshots added or replaced to reflect the current UI
  • Fixed all markdown warnings/errors and added .markdownlint.json configuration
  • Doc cleanup: Fixed stale links, grammar, spelling issues, deprecated folder descriptions, and undocumented switches across all sections

Examples

  • Terraform example revamped: Migrated from Shell scripts to the official Azure IPAM Terraform provider
  • Azure ESLZ example modernized: Updated resource API references, modern coding standards, and improved parameterization
  • Script examples reorganized: PowerShell and Shell scripts moved into a dedicated examples/scripts/ folder with new helper scripts and README
  • Token helper function: Standardized access token generation; removed legacy Microsoft Graph SDK v1 support

Testing

  • Added tests for Virtual Network Association permutations
  • Expanded overall testing coverage with numerous additional Pester tests
  • Updated test expectations to align with additionally created resources
  • CI lint gate: Added pre-deployment lint job to the testing workflow (ESLint, Vite build verification, Ruff for Python, Bicep template validation, Hadolint for Dockerfiles). Deploy is skipped if any check fails, preventing wasted Azure resources

Bug Fixes

[major]

…that were not being accounted for properly
…ue to improper handling of missing vNETs and vHUBs
DCMattyG added 30 commits June 1, 2026 10:34
Update-AzADApplication/Get-AzADApplication were called with -ApplicationId
(AppId), forcing an AppId->ObjectId lookup in Microsoft Graph that can fail
right after app creation due to replication delay, surfacing as "Cannot bind
argument to parameter 'Id' because it is an empty string." Switch to -ObjectId
($app.Id), the native replication-safe key, fixing CI deploy failures on newer
Az/Microsoft.Graph module versions.
Add `if: always()` to the Upload Logs step so failure logs are captured
alongside successful runs. Fall back to a "FAILED" suffix when ipamSuffix is
empty and skip upload gracefully when no log files exist, so a failed deploy
surfaces its real error instead of a secondary log-upload error.
The Engine App references the newly created UI App's AppId as a Known
Client Application. Microsoft Graph intermittently rejects this with
"Property api.knownClientApplications is invalid." when the UI App has
not yet replicated. Poll Get-AzADApplication until the UI App is
discoverable (up to 60s) before creating the Engine App.
Newly created app registrations are not immediately discoverable in
Microsoft Graph due to replication delay, causing intermittent failures:
- Engine App creation rejecting the UI App as a Known Client Application
  ("Property api.knownClientApplications is invalid.")
- Updating the Engine API endpoint failing with "Resource '<id>' does
  not exist or one of its queried reference-property objects are not
  present."

Poll Get-AzADApplication for both the UI App and Engine App (up to 60s
each) until they are discoverable before referencing/updating them.
…to a retry helper

Replace the propagation-wait polling loops and per-operation retry blocks
with a single silent Invoke-WithGraphRetry helper. Retry the actual Graph
operations (engine app create, API endpoint update, UI/engine SP creation)
rather than polling a proxy read, closing the time-of-check/time-of-use gap.
Keep the idempotent SP existence checks; surface only the net result.
Route the UI resource access update, post-create app/SP reads, engine secret
creation, and admin-consent SP fetches through Invoke-WithGraphRetry to absorb
replication delay at every point a freshly-created AD object is referenced.
Construct the shared aiohttp TCPConnector/ClientSession lazily in the
SHARED_TRANSPORT property instead of at import time. Newer aiohttp requires a
running event loop when these are created; building them during module import
(before uvicorn starts the loop) raised "no running event loop" and crash-looped
the engine on startup.
Get-AzADServicePrincipal returns $null without throwing when a freshly created
service principal has not yet replicated, so Invoke-WithGraphRetry never retried
and admin consent failed with "Invalid clientId:" (empty). Throw on an empty
result so the retry loop engages until the SP is visible.
Build the shared CosmosClient and its ManagedIdentityCredential lazily via
get_cosmos_client(), and create the shared aiohttp transport lazily in
globals.SHARED_TRANSPORT. Constructing these at import (in helper.py's
module scope, before uvicorn started the event loop) created an aiohttp
ClientSession/TCPConnector with no running loop, crash-looping the engine
under newer aiohttp. All Azure async clients are now instantiated on first
use within a running loop; main.py and the routers already did so.
…rincipals

New-MgOauth2PermissionGrant runs against the Microsoft Graph endpoint, which may
not yet have a freshly created service principal that Az (ARM) already returned,
causing "Specified resourceId was not found". Wrap the grant calls in
Invoke-WithGraphRetry so admin consent tolerates cross-service replication lag.
Replace the fixed 5s delay in Invoke-WithGraphRetry with capped exponential
backoff plus jitter (BaseDelaySeconds * 2^(attempt-1), capped at
MaxDelaySeconds, scaled by a random factor). This tolerates both fast and slow
Azure AD replication and avoids synchronized retries from concurrent callers
stampeding a throttled endpoint. Retry-on-any-error behavior is unchanged;
errors are deliberately not classified by message text.
Piping Get-AzADApplication output into Remove-AzADApplication bound the object's
directory ObjectId onto -ApplicationId under Az.Resources 9.1.0, so Graph looked
the ObjectId up as a client AppId and failed with "Resource 'Application_<id>'
does not exist" despite the app existing. Remove by explicit -ObjectId to avoid
the parameter-binding ambiguity.
Drop the LoadingButton import from @mui/lab and update the
commented-out WIP usages in DialogActions to use Button instead,
since @mui/material's Button now supports the `loading` prop
natively.
reordered App Registration and Service Principal cleanup process.
…skipping explicit Service Principal removal.
Ran `npx @mui/codemod@latest deprecations/dialog-props src`.
manageEndpoints.jsx is the only real migration; Table.jsx and
newReservation.jsx are cosmetic recast reformatting.
…I v9)

Ran `npx @mui/codemod@latest deprecations/menu-props src` to convert
MenuListProps -> slotProps.list (generator.jsx, DataGrid.jsx).

The codemod doesn't handle Menu's PaperProps even though v9 removed it,
so migrated the 5 remaining sites manually to slotProps.paper:
- drawer.jsx (2x)
- manageEndpoints.jsx
- space.jsx
- block.jsx

Verified no PaperProps={ usages remain in src/ and no lint errors.
Ran `npx @mui/codemod@latest deprecations/tooltip-props src`.
Touched InfoCellRenderer.jsx and admin.jsx — both purely mechanical
PopperProps -> slotProps.popper conversions.
Ran `npx @mui/codemod@latest deprecations/autocomplete-props src`,
touching 11 files. Verified against the v9 Autocomplete API:
- componentsProps -> slotProps
- ListboxProps -> slotProps.listbox
- PopperComponent -> slots.popper
- renderInput's <TextField InputProps={...params.InputProps}>
  -> <TextField slotProps={{...params.slotProps, input: {...}}}>
Ran `npx @mui/codemod@latest deprecations/text-field-props src`.
Affected 10 files:
- TextField inputProps -> slotProps.htmlInput
- TextField InputProps -> slotProps.input

The 2 remaining inputProps usages on OutlinedInput are intentionally
left alone — OutlinedInput still accepts inputProps in v9.
settings.jsx imported `Unstable_Grid2 as Grid` from @mui/material,
which v9 removed (the new Grid IS the former Grid2). The v7.0.0/grid-props
codemod looks for named imports of `Grid`, not aliased `Unstable_Grid2`,
so this had to be done manually.

- Import: Unstable_Grid2 as Grid -> Grid
- <Grid xs={N}> -> <Grid size={{ xs: N }}>
Ran `npx @mui/codemod@latest v9.0.0/system-props src`, touching 23 files.

For Box/Stack/Typography/Link/Grid/DialogContentText components, props
like display, alignItems, justifyContent, position, top/left/right/bottom,
mt/mb/ml/mr, etc. have been moved from component-level props into the sx
prop. Typography palette tokens (e.g. color="textSecondary") were correctly
preserved per the v9 API.
…I v9)

The menu-props codemod doesn't recurse into Select's nested MenuProps,
so this had to be done manually per the v9 migration guide.
- Consolidated `styled`, `createTheme`, `ThemeProvider` into one
  import from `@mui/material/styles` (replaces direct `@mui/system`
  dep).
- Rewrote v4-era `overrides:` block as v9 `components.MuiCircularProgress.styleOverrides`,
  restoring the original rounded/thicker progress-circle styling that
  has been silently disabled since v5.
- Dropped the dead `MuiLinearProgress` overrides — no `<LinearProgress>`
  is rendered inside this ThemeProvider's subtree.
v9 removed 23 legacy icon exports that ended with `Outline` (no 'd').
Renamed all in-use ones to their `Outlined` counterparts:

- DeleteOutline -> DeleteOutlined (4 files)
- ErrorOutline  -> ErrorOutlined  (reservations.jsx)
- PieChartOutline -> PieChartOutlined (block.jsx)

For aliased imports (e.g. `DeleteOutline as DeleteOutlineIcon`),
only the imported name was changed; usage sites kept their local alias.
Upgrades all workflow actions to address the Node.js 20 deprecation
warning and align with the latest available versions:

- actions/checkout              v4     -> v6
- actions/setup-node            v4     -> v6
- actions/setup-python          v5     -> v6
- actions/github-script         v7     -> v9
- actions/create-github-app-token v2   -> v3
- azure/login                   v2     -> v3
- hadolint/hadolint-action      v3.1.0 -> v3.3.0
…plugin-react-hooks@7

React Compiler 1.0 consolidated its lint rules into eslint-plugin-react-hooks@^7;
the standalone eslint-plugin-react-compiler package is deprecated and pulled in
the deprecated @babel/plugin-proposal-private-methods as a transitive dependency.

* Swap eslint-plugin-react-compiler@19.1.0-rc.2 for eslint-plugin-react-hooks@7.1.x
* Adopt reactHooks.configs.flat['recommended-latest'] preset
* Disable react-hooks/set-state-in-effect (preserves prior incremental-cleanup stance)
* Move ref-during-render assignments in refresh.jsx into useEffect (react-hooks/refs)
* Suppress per-line known intentional patterns in DataGrid, manageEndpoints, peering
Hadolint v3.3.0 bundles a newer hadolint binary that newly enforces
DL3041 (pin dnf install package versions). This mirrors the existing
DL3008 suppression for apt — OS package version pinning makes
base-image rebuilds brittle since distro repos don't retain old
patch versions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants