Skip to content

[AppService] az functionapp flex-migration start: Add in-place CV1 to Flex Consumption upgrade support - #33863

Open
Sreemoyee Sadhukhan (Sreemoyee26) wants to merge 6 commits into
Azure:devfrom
Sreemoyee26:user/ssadhukhan/functionsCV1-upgrade
Open

[AppService] az functionapp flex-migration start: Add in-place CV1 to Flex Consumption upgrade support#33863
Sreemoyee Sadhukhan (Sreemoyee26) wants to merge 6 commits into
Azure:devfrom
Sreemoyee26:user/ssadhukhan/functionsCV1-upgrade

Conversation

@Sreemoyee26

@Sreemoyee26 Sreemoyee Sadhukhan (Sreemoyee26) commented Aug 7, 2026

Copy link
Copy Markdown

🤖 PR Validation — ⚠️ Review suggested

Breaking Changes Tests
⚠️ None 🔄 130/130
⚠️AzureCLI-BreakingChangeTest
⚠️appservice
rule cmd_name rule_message suggest_message
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter always_ready_instances
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter deployment_storage_auth_type
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter deployment_storage_auth_value
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter deployment_storage_container_name
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter deployment_storage_name
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter in_place
⚠️ 1006 - ParaAdd functionapp flex-migration start cmd functionapp flex-migration start added parameter instance_memory
⚠️ 1009 - ParaPropRemove functionapp flex-migration start cmd functionapp flex-migration start update parameter name: removed property required=True
⚠️ 1009 - ParaPropRemove functionapp flex-migration start cmd functionapp flex-migration start update parameter resource_group: removed property required=True

Summary

Add in-place CV1 Linux Consumption to Flex Consumption upgrade support through the new --in-place flag. The command upgrades the source app directly, preserving its name and hostname instead of creating a side-by-side app.

The implementation also:

  • Adds deployment-storage and scale configuration parameters.
  • Preserves existing app settings.
  • Configures deployment storage before server-side content migration.
  • Sends the top-level Flex Consumption SKU expected by the service.
  • Removes CV1-only configuration rejected during the Flex update.
  • Updates command help and examples.
  • Adds mocked and live scenario tests.

Related command

az functionapp flex-migration start

Description

When --in-place is specified, the command validates the source Linux Consumption app, builds its Flex Consumption configuration, configures deployment storage, and updates the existing site. Existing side-by-side migration behavior remains unchanged when --in-place is omitted.

Testing Guide

  • Mocked tests: 7 passed for TestFlexMigrationInPlaceMocked.
  • Azure CLI PR validation: 130/130 tests passed.
  • Fresh end-to-end validation in NCUS Stage:
    • Created a new resource group and Python 3.11 Linux Consumption app.
    • Deployed and invoked an HTTP-triggered function before migration (HTTP 200).
    • Ran:
      az functionapp flex-migration start --source-name cv1-flex-verify2-app --source-resource-group rg-cv1-flex-verify2 --in-place
    • Verified SKU FlexConsumption, state Running, Python 3.11 runtime, deployment storage, and DEPLOYMENT_STORAGE_CONNECTION_STRING.
    • Invoked the function after migration (HTTP 200).

… to Flex upgrade

Add in-place CV1 Linux Consumption -> Flex Consumption upgrade support
to the existing 'az functionapp flex-migration start' command via a new
'--in-place' flag. When set, the command upgrades the source app directly
(same app, same name, same hostname) instead of creating a new side-by-side
app.

Changes:
- custom.py: Add in_place branching + _upgrade_consumption_to_flex_in_place()
- _params.py: Add --in-place/-i and deployment-storage/scale params
- _help.py: Update group summary and add in-place example
- tests: Add 7 mock unit tests + 4 live scenario tests

Design: based on cv1-to-flex-upgrade-uber-design/14-azure-cli.md

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

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

@microsoft-github-policy-service microsoft-github-policy-service Bot added customer-reported Issues that are reported by GitHub users external to the Azure organization. Auto-Assign Auto assign by bot Functions az functionapp act-observability-squad labels Aug 7, 2026
@Sreemoyee26 Sreemoyee Sadhukhan (Sreemoyee26) changed the title feat(appservice): add --in-place flag to flex-migration start for CV1… feat(appservice): Add --in-place flag to cv1 to flex-migration Aug 7, 2026
@Sreemoyee26 Sreemoyee Sadhukhan (Sreemoyee26) changed the title feat(appservice): Add --in-place flag to cv1 to flex-migration feat(appservice): Add --in-place flag for cv1 to flex upgrade support Aug 7, 2026
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

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

@yonzhan

Copy link
Copy Markdown
Collaborator

appservice

…eLimit) before Flex PUT

The GET-mutate-PUT pattern carries CV1-specific siteConfig properties that the
server rejects for Flex Consumption sites. Clear linux_fx_version and
function_app_scale_limit before submitting the upgrade PUT request.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

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

The server-side SkuTransitionResolver reads siteEnvelope.Sku.Name (top-level),
not properties.sku. The SDK Site model serializes sku into properties, so we
serialize to dict and inject the top-level sku: {name: 'FlexConsumption'}
manually. This enables the CV1-to-Flex upgrade orchestrator to fire correctly.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

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

…er upgrade

The site PUT's siteConfig.appSettings is ignored by the SkuTransitionResolver
orchestrator during the CV1->Flex upgrade. The orchestrator preserves only the
settings from /config/appsettings, discarding anything in the PUT body's
siteConfig.appSettings.

Move the DEPLOYMENT_STORAGE_CONNECTION_STRING setting to a separate
update_application_settings call after the upgrade completes, merging it with
existing settings rather than replacing them.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

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

Ensure the deployment storage connection setting is available to the server-side content migration step, and trim redundant comments in the in-place upgrade helper.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Sreemoyee26 Sreemoyee Sadhukhan (Sreemoyee26) changed the title feat(appservice): Add --in-place flag for cv1 to flex upgrade support [AppService] az functionapp flex-migration start: Add in-place CV1 to Flex Consumption upgrade support Aug 17, 2026
Extract target argument validation to reduce branch complexity and reuse the module-level validator import.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@a0x1ab

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

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

@Sreemoyee26
Sreemoyee Sadhukhan (Sreemoyee26) marked this pull request as ready for review August 17, 2026 16:54
Copilot AI lite review requested due to automatic review settings August 17, 2026 16:54
@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

Adds an --in-place mode to az functionapp flex-migration start to upgrade an existing CV1 Linux Consumption function app directly to Flex Consumption (preserving app name/hostname), alongside new scale/deployment-storage parameters, updated help, and new live + mocked tests.

Changes:

  • Add --in-place execution branch with deployment storage + scale configuration support in migrate_consumption_to_flex.
  • Extend CLI parameters/help text to describe in-place vs side-by-side migration and new deployment-storage/scale flags.
  • Add scenario (live) and mocked tests covering in-place argument validation and basic migration behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/azure-cli/azure/cli/command_modules/appservice/custom.py Adds --in-place validation and an in-place upgrade implementation that configures deployment storage and Flex config on the existing site.
src/azure-cli/azure/cli/command_modules/appservice/_params.py Adds --in-place and new scale/deployment-storage arguments for functionapp flex-migration start.
src/azure-cli/azure/cli/command_modules/appservice/_help.py Updates help text and adds an in-place usage example.
src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py Adds live scenario coverage for in-place migration and CLI-level negative-path checks.
src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands_thru_mock.py Adds mocked/unit tests validating --in-place argument semantics and eligibility checks.
Suppressed comments (1)

src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py:1401

  • Same as above: this negative-path LiveScenarioTest should use expect_failure=True (the common pattern in this test file) instead of assertRaises(SystemExit).
    def test_functionapp_flex_migration_side_by_side_requires_target_args(self):
        """Side-by-side without --name/--resource-group should fail."""
        with self.assertRaises(SystemExit):
            self.cmd('functionapp flex-migration start --source-resource-group rg --source-name app')


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

Comment on lines +1444 to +1458
deployment_storage_auth_config = {"type": deployment_storage_auth_type}

app_settings_to_add = []
if deployment_storage_auth_type == 'UserAssignedIdentity':
deployment_storage_user_assigned_identity = _get_or_create_user_assigned_identity(
cmd, source_resource_group, source_name, deployment_storage_auth_value, source.location)
deployment_storage_auth_value = deployment_storage_user_assigned_identity.id
deployment_storage_auth_config["userAssignedIdentityResourceId"] = deployment_storage_auth_value
elif deployment_storage_auth_type == 'StorageAccountConnectionString':
deployment_storage_conn_string = _get_storage_connection_string(cmd.cli_ctx, deployment_storage)
conn_string_app_setting = deployment_storage_auth_value or 'DEPLOYMENT_STORAGE_CONNECTION_STRING'
app_settings_to_add.append({'name': conn_string_app_setting, 'value': deployment_storage_conn_string})
deployment_storage_auth_value = conn_string_app_setting
deployment_storage_auth_config["storageAccountConnectionStringName"] = deployment_storage_auth_value

Comment on lines +1383 to +1387
result = self.cmd(
'functionapp flex-migration start --source-resource-group {} --source-name {} --in-place '
'--deployment-storage-name {} --deployment-storage-container-name mycontainer'
.format(resource_group, src_name, storage_account)
).get_output_in_json()
Comment on lines +1391 to +1396
def test_functionapp_flex_migration_in_place_rejects_target_args(self):
"""--in-place with --name should fail."""
with self.assertRaises(SystemExit):
self.cmd('functionapp flex-migration start --source-resource-group rg --source-name app '
'--in-place --name target-app --resource-group target-rg')

Comment on lines +1234 to +1236
- name: Upgrade a Linux Consumption function app to Flex Consumption in place (same app, same name).
text: >
az functionapp flex-migration start --source-name MyLinuxConsumptionApp --source-resource-group MyResourceGroup --in-place
@a0x1ab Aditya Pujara (a0x1ab) added the Azure Client Tools Agent Requested Request Azure Client Tools Agent testing and review label Aug 19, 2026
@azure-client-tools-agent

Copy link
Copy Markdown
Contributor

Live test results — azdev test --live --series (changed test files only)

FAIL (exit 1)

Selectors: test_functionapp_commands test_functionapp_commands_thru_mock (module)
PR head ref: user/ssadhukhan/functionsCV1-upgrade
PR head sha: 55dee2d6bb5cb686a49cbabba0ad785662c7dfbb
PR base ref: dev
New test files in PR: false

Changed test files run
src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py
src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands_thru_mock.py

Workflow run: https://github.com/Azure/issue-sentinel/actions/runs/32223806842

Live-test recordings: 1 regenerated — archived in workflow artifact live-test-pr-33863 (recordings/).

ℹ️ This PR is from a fork, so recordings were not pushed automatically. Download them from the artifact and commit to your branch.

Recording files
src/azure-cli/azure/cli/command_modules/appservice/tests/latest/recordings/test_acr_integration_function_app.yaml
Last 80 lines of azdev output
.venv/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
azure-cli/src/azure-cli-core/azure/cli/core/__init__.py:153: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

ex = CLIError('Operation cannot be completed without additional quota. \r\nAdditional details - Location:  \r\nCurrent Limi...ota requirements of these operations, you will need to request a higher quota limit than the one currently displayed.')
args = (), kwargs = {}

    def _handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

azure-cli/src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.appservice.tests.latest.test_functionapp_commands.FunctionappACRScenarioTest testMethod=test_acr_integration_function_app>
resource_group = 'clitest.rg4iau2xh3c27jh5gao4ec3jwrimbxuuaz5qfbraikb2sd2t5bjaomgjlsbhzvwb7mm'
storage_account = 'clitest2gerppgedefffy6au'

    @ResourceGroupPreparer(location='eastus')
    @StorageAccountPreparer()
    @AllowLargeResponse()
    def test_acr_integration_function_app(self, resource_group, storage_account):
        plan = self.create_random_name(prefix='acrtestplanfunction', length=24)
        functionapp = self.create_random_name(
            prefix='functionappacrtest', length=24)
        runtime = 'node'
        acr_registry_name = functionapp
        self.cmd('acr create --admin-enabled -g {} -n {} --sku Basic'.format(
            resource_group, acr_registry_name))
>       self.cmd(
            'appservice plan create -g {} -n {} --sku S1 --is-linux' .format(resource_group, plan))

azure-cli/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_functionapp_commands.py:47: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
azure-cli/src/azure-cli-testsdk/azure/cli/testsdk/base.py:177: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
azure-cli/src/azure-cli-testsdk/azure/cli/testsdk/base.py:252: in __init__
    self._in_process_execute(cli_ctx, command, expect_failure=expect_failure)
azure-cli/src/azure-cli-testsdk/azure/cli/testsdk/base.py:315: in _in_process_execute
    raise ex.exception
.venv/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
azure-cli/src/azure-cli-core/azure/cli/core/commands/__init__.py:677: in execute
    raise ex
azure-cli/src/azure-cli-core/azure/cli/core/commands/__init__.py:820: in _run_jobs_serially
    results.append(self._run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
azure-cli/src/azure-cli-core/azure/cli/core/commands/__init__.py:812: in _run_job
    return cmd_copy.exception_handler(ex)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

ex = CLIError('Operation cannot be completed without additional quota. \r\nAdditional details - Location:  \r\nCurrent Limi...ota requirements of these operations, you will need to request a higher quota limit than the one currently displayed.')

    def _ex_handler(ex):
        ex = _polish_bad_errors(ex, creating_plan)
>       raise ex
E       knack.util.CLIError: Operation cannot be completed without additional quota. 
E       Additional details - Location:  
E       Current Limit (Total VMs): 0 
E       Current Usage: 0
E       Amount required for this deployment (Total VMs): 1 
E       (Minimum) New Limit that you should request to enable this deployment: 1. 
E       Note that if you experience multiple scaling operations failing (in addition to this one) and need to accommodate the aggregate quota requirements of these operations, you will need to request a higher quota limit than the one currently displayed.

azure-cli/src/azure-cli/azure/cli/command_modules/appservice/commands.py:137: CLIError
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 54.25s ==============================

Posted by agent-assist live-test workflow.

@azure-client-tools-agent azure-client-tools-agent Bot 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.

⚠️ Live Test Failed

The scoped live test run (azdev test, running only the test files this PR changed) failed:

CI checks: 45/53 completed and passed, 0 failed; 2 checks (Azure.azure-cli Full Test,
Azure.azure-cli) have been stuck queued for ~38 hours and could not be re-triggered — these
appear to be abandoned/zombie checks rather than active failures, so they are not blocking this
summary.

Since this is a human-authored PR (reviewer requested), please check the live test run logs above and
address the failure directly; the automation will not open a Copilot fix session for a
human-driven PR. You may also want to re-run or re-queue the stuck Azure Pipelines checks manually.

@azure-client-tools-agent azure-client-tools-agent Bot added azure-client-tools-agent Pull request reviewed by Azure Client Tools Agent and removed Azure Client Tools Agent Requested Request Azure Client Tools Agent testing and review labels Aug 19, 2026
@microsoft-github-policy-service

Copy link
Copy Markdown
Contributor

🔔 Routing this PR to @Azure/act-observability-squad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

act-observability-squad Auto-Assign Auto assign by bot azure-client-tools-agent Pull request reviewed by Azure Client Tools Agent customer-reported Issues that are reported by GitHub users external to the Azure organization. Functions az functionapp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants