Skip to content

Allow Template upgrade properties to be set and remove properties that no longer exist.#4783

Open
JC-wk wants to merge 50 commits into
microsoft:mainfrom
JC-wk:template-upgrade-properties
Open

Allow Template upgrade properties to be set and remove properties that no longer exist.#4783
JC-wk wants to merge 50 commits into
microsoft:mainfrom
JC-wk:template-upgrade-properties

Conversation

@JC-wk

@JC-wk JC-wk commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Resolves #4732 #4730

What is being addressed

Currently if you add a new property to a template there is no way to specify this property before an upgrade is ran.
The upgrade may fail due to the missing property (although the template version is still incremented)
The user then has to click update and supply the property.
Similarly when removing a property from a template and running an upgrade, the property still exists on the resource.

Todo

How is this addressed

  • Adds a form to allow the user to specify new properties prior to the upgrade
  • Removes any template properties that no longer exist in the new template
  • Added tests
  • Updated CHANGELOG.md
  • Increment API version
image image

James Chapman and others added 11 commits December 10, 2025 15:23
This commit aligns the resource upgrade process with the update process by correctly handling conditional properties in the JSON schema.

- The schema generation logic in `ConfirmUpgradeResource.tsx` is updated to include conditional blocks (`if`/`then`/`else`) when the condition is based on an existing property.
- New read-only properties are now submitted during the upgrade process.
This commit aligns the resource upgrade process with the update process by correctly handling conditional properties in the JSON schema.

- The schema generation logic in `ConfirmUpgradeResource.tsx` is updated to include conditional blocks (`if`/`then`/`else`) when the condition is based on an existing property.
- New read-only properties are now submitted during the upgrade process.
- The `liveOmit` prop is added to the form to prevent the submission of unevaluated properties from conditionally hidden fields.
…1346005040390942732

Fix Upgrade Conditional Properties
@JC-wk JC-wk requested a review from a team as a code owner December 16, 2025 09:54
@github-actions

github-actions Bot commented Dec 16, 2025

Copy link
Copy Markdown

Unit Test Results

933 tests   933 ✅  37s ⏱️
 28 suites    0 💤
  2 files      0 ❌

Results for commit dc1714f.

♻️ This comment has been updated with latest results.

@JC-wk JC-wk marked this pull request as draft December 16, 2025 10:02
@JC-wk JC-wk marked this pull request as ready for review June 9, 2026 09:49
Copilot AI review requested due to automatic review settings June 9, 2026 09:49

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

This PR enhances the Azure TRE upgrade flow so that template upgrades can accept values for newly introduced template properties and remove properties that no longer exist in the target template, reducing upgrade failures and lingering stale properties.

Changes:

  • UI: adds an upgrade-time form to capture values for newly added template properties (including handling hidden properties/defaults).
  • API: adjusts patch validation to allow setting newly introduced (previously non-existent) properties during an upgrade and removes properties absent from the new template.
  • Tests/versioning: adds/updates unit tests and increments UI/API versions; updates the changelog.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
ui/app/src/components/shared/ConfirmUpgradeResource.tsx Fetches current/target template schemas to detect added/removed properties and renders an upgrade-time form for new properties.
ui/app/src/components/shared/ConfirmUpgradeResource.test.tsx Extends UI tests to cover schema loading, new/removed property messaging, and upgrade payload contents.
api_app/db/repositories/resources.py Allows new properties during upgrades, permits pipeline-substituted fields, and removes properties not present in the upgraded template.
api_app/tests_ma/test_db/test_repositories/test_resource_repository.py Adds/updates repository validation tests for upgrade scenarios and pipeline property handling.
ui/app/package.json Bumps UI version.
ui/app/package-lock.json Updates lockfile version metadata to match UI version bump.
api_app/_version.py Bumps API version.
CHANGELOG.md Adds an enhancement entry describing the upgrade property behavior.
Files not reviewed (1)
  • ui/app/package-lock.json: Language not supported

Comment on lines +37 to +50
// Utility to get all property keys from template schema's properties object recursively, flattening nested if needed
const getAllPropertyKeys = (properties: any, prefix = ""): string[] => {
if (!properties) return [];
let keys: string[] = [];
for (const [key, value] of Object.entries(properties)) {
if (value && typeof value === "object" && 'properties' in value) {
// recur for nested properties
keys = keys.concat(getAllPropertyKeys(value["properties"], prefix + key + "."));
} else {
keys.push(prefix + key);
}
}
return keys;
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

If we had used the simplified Object.keys(properties) approach (Option 2) suggested by Copilot:

• An upgrade from a template with parent: { child } to parent: { child, sibling } would result in both
versions having the top-level key parent .
• Comparing them would yield [] (no new properties detected).
• The upgrade would proceed silently without giving the user a chance to supply a value for the new sibling
property, causing backend validation failures or incomplete deployments.

By keeping the recursive dotted-path detection but updating the form state management, validation, and API call
generation to handle nested objects correctly:

  1. Accurate Detection: We correctly identify when a nested property (e.g., parent.sibling ) is added/removed.
  2. Object Structure Alignment: We keep newPropertyValues in the nested object shape that the RJSF Form and
    the backend PATCH API expect (e.g., { parent: { child: '...', sibling: '...' } } ).
  3. Data Preservation: We pre-populate existing sibling values (e.g., keeping parent.child ) so they aren't lost
    or cleared during the upgrade.
  4. Validation Resolution: We use ConfirmUpgradeResource.tsx to check if the new nested fields are filled,
    preventing the
    "Upgrade" button from being permanently disabled.

Comment on lines +292 to +300
// prefill newPropertyValues with schema defaults or empty string (excluding pipeline properties)
setNewPropertyValues(
newPropKeysToSend.reduce((acc, key) => {
// Get top-level portion of the key
const topKey = key.split('.')[0];
const defaultValue = newTemplate?.properties?.[topKey]?.default;
acc[key] = defaultValue !== undefined ? defaultValue : '';
return acc;
}, {} as any),
Comment on lines +454 to +460
primaryDisabled={
!selectedVersion ||
(newPropertiesToFill.length > 0 &&
newPropertiesToFill.some(
(key) => newPropertyValues[key] === "" || newPropertyValues[key] === undefined,
))
}
Comment on lines +114 to +122
def _get_all_property_keys_from_template(self, resource_template: ResourceTemplate) -> set:
properties = set(resource_template.properties.keys())
if "allOf" in resource_template:
for condition in resource_template.allOf:
if "then" in condition and "properties" in condition["then"]:
properties.update(condition["then"]["properties"].keys())
if "else" in condition and "properties" in condition["else"]:
properties.update(condition["else"]["properties"].keys())
return properties
Comment thread api_app/db/repositories/resources.py Outdated

if resource_patch.templateVersion is not None:
await self.validate_template_version_patch(resource, resource_patch, resource_template_repo, resource_template, force_version_update)
new_template = await resource_template_repo.get_template_by_name_and_version(resource.templateName, resource_patch.templateVersion, resource.resourceType)
Comment thread api_app/db/repositories/resources.py Outdated
# get the schema for the target version if upgrade is happening
if resource_patch.templateVersion is not None:
# fetch the template for the target version
target_template = await resource_template_repo.get_template_by_name_and_version(resource_template.name, resource_patch.templateVersion, resource_template.resourceType)
Comment thread CHANGELOG.md Outdated
* Remove Windows 10 and dsvm image support from Guacamole. ([#4890](https://github.com/microsoft/AzureTRE/issues/4890))

ENHANCEMENTS:
* Allow new template properties to be specified during template upgrades. Remove Template properties that no longer exist.
Comment on lines +681 to +685
// Click upgrade
await waitFor(() => {
const upgradeButton = screen.getByTestId("primary-button");
fireEvent.click(upgradeButton);
});
Enhance template upgrade functionality and improve resource handling

- Allow new template properties to be specified during

upgrades and remove obsolete properties.
- Update resource repository methods to handle parent service names for user resources.
- Add tests for nested properties and enum value handling in upgrade scenarios.
- Refactor ConfirmUpgradeResource component to manage nested properties and validation more effectively.
- Update TypeScript configuration for improved compatibility.
Comment thread ui/app/src/components/shared/ConfirmUpgradeResource.tsx Fixed

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

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • ui/app/package-lock.json: Language not supported

}
return false;
});
const removedPropsArray = currentKeys.filter((k) => !newKeys.includes(k));
Comment on lines +338 to +343
const newSchemaProps = newTemplate?.properties || {};
const currentProps = currentTemplate?.properties || {};

const newKeys = getAllPropertyKeys(newSchemaProps);
const currentKeys = getAllPropertyKeys(currentProps);
const newPropKeys = newKeys.filter((key) => {
James Chapman and others added 3 commits June 9, 2026 10:48
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.

When upgrading a template that has a new property the user should be prompted to enter it or the defaults used (if provided)

3 participants