8
8
using System . Net . Http . Headers ;
9
9
using System . Threading ;
10
10
using System . Threading . Tasks ;
11
+ using Azure . Core ;
11
12
using Azure . Functions . Cli . Actions . LocalActions ;
12
- using Azure . Functions . Cli . Arm . Models ;
13
13
using Azure . Functions . Cli . Common ;
14
- using Azure . Functions . Cli . Diagnostics ;
15
14
using Azure . Functions . Cli . Extensions ;
16
15
using Azure . Functions . Cli . Helpers ;
17
16
using Azure . Functions . Cli . Interfaces ;
18
17
using Azure . Functions . Cli . StacksApi ;
19
18
using Colors . Net ;
20
19
using Fclp ;
21
- using Microsoft . Build . Framework ;
22
20
using Microsoft . WindowsAzure . Storage ;
23
21
using Microsoft . WindowsAzure . Storage . Blob ;
24
22
using Newtonsoft . Json ;
25
- using NuGet . Common ;
26
23
using static Azure . Functions . Cli . Common . OutputTheme ;
24
+ using Site = Azure . Functions . Cli . Arm . Models . Site ;
27
25
28
26
namespace Azure . Functions . Cli . Actions . AzureActions
29
27
{
@@ -34,7 +32,7 @@ internal class PublishFunctionAppAction : BaseFunctionAppAction
34
32
35
33
private readonly ISettings _settings ;
36
34
private readonly ISecretsManager _secretsManager ;
37
- private static string _requiredNetFrameworkVersion = "6 .0" ;
35
+ private static string _requiredNetFrameworkVersion = "8 .0" ;
38
36
39
37
public bool PublishLocalSettings { get ; set ; }
40
38
public bool OverwriteSettings { get ; set ; }
@@ -268,7 +266,14 @@ private async Task<IDictionary<string, string>> ValidateFunctionAppPublish(Site
268
266
}
269
267
}
270
268
271
- if ( functionApp . AzureAppSettings . TryGetValue ( Constants . FunctionsWorkerRuntime , out string workerRuntimeStr ) )
269
+ string workerRuntimeStr = null ;
270
+ if ( functionApp . IsFlex )
271
+ {
272
+ workerRuntimeStr = functionApp . FunctionAppConfig . runtime . name ;
273
+ }
274
+
275
+ if ( ( functionApp . IsFlex && ! string . IsNullOrEmpty ( workerRuntimeStr ) ||
276
+ ( ! functionApp . IsFlex && functionApp . AzureAppSettings . TryGetValue ( Constants . FunctionsWorkerRuntime , out workerRuntimeStr ) ) ) )
272
277
{
273
278
var resolution = $ "You can pass --force to update your Azure app with '{ workerRuntime } ' as a '{ Constants . FunctionsWorkerRuntime } '";
274
279
try
@@ -312,7 +317,18 @@ private async Task<IDictionary<string, string>> ValidateFunctionAppPublish(Site
312
317
throw new CliException ( $ "Azure Functions Core Tools does not support this deployment path. Please configure the app to deploy from a remote package using the steps here: https://aka.ms/deployfromurl") ;
313
318
}
314
319
315
- await UpdateFrameworkVersions ( functionApp , workerRuntime , DotnetFrameworkVersion , Force , azureHelperService ) ;
320
+ if ( functionApp . IsFlex )
321
+ {
322
+ if ( result . ContainsKey ( Constants . FunctionsWorkerRuntime ) )
323
+ {
324
+ await UpdateRuntimeConfigForFlex ( functionApp , WorkerRuntimeLanguageHelper . GetRuntimeMoniker ( workerRuntime ) , null , azureHelperService ) ;
325
+ result . Remove ( Constants . FunctionsWorkerRuntime ) ;
326
+ }
327
+ }
328
+ else
329
+ {
330
+ await UpdateFrameworkVersions ( functionApp , workerRuntime , DotnetFrameworkVersion , Force , azureHelperService ) ;
331
+ }
316
332
317
333
// Special checks for python dependencies
318
334
if ( workerRuntime == WorkerRuntime . python )
@@ -321,10 +337,12 @@ private async Task<IDictionary<string, string>> ValidateFunctionAppPublish(Site
321
337
await PythonHelpers . WarnIfAzureFunctionsWorkerInRequirementsTxt ( ) ;
322
338
// Check if remote LinuxFxVersion exists and is different from local version
323
339
var localVersion = await PythonHelpers . GetEnvironmentPythonVersion ( ) ;
324
- if ( ! PythonHelpers . IsLinuxFxVersionRuntimeVersionMatched ( functionApp . LinuxFxVersion , localVersion . Major , localVersion . Minor ) )
340
+
341
+ if ( ( ! functionApp . IsFlex && ! PythonHelpers . IsLinuxFxVersionRuntimeVersionMatched ( functionApp . LinuxFxVersion , localVersion . Major , localVersion . Minor ) ) ||
342
+ ( functionApp . IsFlex && ! PythonHelpers . IsFlexPythonRuntimeVersionMatched ( functionApp . FunctionAppConfig ? . runtime ? . name , functionApp . FunctionAppConfig ? . runtime ? . version , localVersion . Major , localVersion . Minor ) ) )
325
343
{
326
344
ColoredConsole . WriteLine ( WarningColor ( $ "Local python version '{ localVersion . Version } ' is different from the version expected for your deployed Function App." +
327
- $ " This may result in 'ModuleNotFound' errors in Azure Functions. Please create a Python Function App for version { localVersion . Major } .{ localVersion . Minor } or change the virtual environment on your local machine to match '{ functionApp . LinuxFxVersion } '.") ) ;
345
+ $ " This may result in 'ModuleNotFound' errors in Azure Functions. Please create a Python Function App for version { localVersion . Major } .{ localVersion . Minor } or change the virtual environment on your local machine to match '{ ( functionApp . IsFlex ? functionApp . FunctionAppConfig . runtime . version : functionApp . LinuxFxVersion ) } '.") ) ;
328
346
}
329
347
}
330
348
@@ -336,6 +354,59 @@ private async Task<IDictionary<string, string>> ValidateFunctionAppPublish(Site
336
354
return result ;
337
355
}
338
356
357
+ public static async Task UpdateRuntimeConfigForFlex ( Site site , string runtimeName , string runtimeVersion , AzureHelperService helperService )
358
+ {
359
+ if ( string . IsNullOrEmpty ( runtimeName ) )
360
+ {
361
+ return ;
362
+ }
363
+
364
+ if ( string . IsNullOrEmpty ( runtimeVersion ) )
365
+ {
366
+ if ( runtimeName . Equals ( "python" , StringComparison . OrdinalIgnoreCase ) )
367
+ {
368
+ var localVersion = await PythonHelpers . GetEnvironmentPythonVersion ( ) ;
369
+ runtimeVersion = $ "{ localVersion . Major } .{ localVersion . Minor } ";
370
+ if ( runtimeVersion != "3.10" && runtimeVersion != "3.11" )
371
+ {
372
+ // todo: default will be 3.11 after 3.11 support is added.
373
+ runtimeVersion = "3.10" ;
374
+ }
375
+ }
376
+ else if ( runtimeName . Equals ( "dotnet-isolated" , StringComparison . OrdinalIgnoreCase ) )
377
+ {
378
+ // Only .NET 8.0 is supported in flex.
379
+ if ( runtimeVersion != "8.0" )
380
+ runtimeVersion = "8.0" ;
381
+ }
382
+ else if ( runtimeName . Equals ( "node" , StringComparison . OrdinalIgnoreCase ) )
383
+ {
384
+ // Only Node 18 is supported.
385
+ if ( runtimeVersion != "18" )
386
+ runtimeVersion = "18" ;
387
+ }
388
+ else if ( runtimeName . Equals ( "powershell" , StringComparison . OrdinalIgnoreCase ) )
389
+ {
390
+ // Only Python 7.2 is supported.
391
+ if ( runtimeVersion != "7.2" )
392
+ runtimeVersion = "7.2" ;
393
+ }
394
+ else if ( runtimeName . Equals ( "java" , StringComparison . OrdinalIgnoreCase ) )
395
+ {
396
+ // Warning: Java is not supported by core tools at the moment.
397
+ ColoredConsole . WriteLine ( WarningColor ( $ "Java is not supported in core tools at the moment. Please use az cli to update the runtime information.") ) ;
398
+ }
399
+ else
400
+ {
401
+ // Warning: Runtime name is unknown.
402
+ ColoredConsole . WriteLine ( WarningColor ( $ "Runtime is not updated. Only dotnet-isolated, node, java, and powershell is supported in core tools for Flex SKU.") ) ;
403
+ return ;
404
+ }
405
+ }
406
+
407
+ await helperService . UpdateFlexRuntime ( site , runtimeName , runtimeVersion ) ;
408
+ }
409
+
339
410
internal static async Task UpdateFrameworkVersions ( Site functionApp , WorkerRuntime workerRuntime , string requestedDotNetVersion , bool force , AzureHelperService helperService )
340
411
{
341
412
if ( workerRuntime == WorkerRuntime . dotnetIsolated )
@@ -686,6 +757,14 @@ await WaitForAppSettingUpdateSCM(functionApp, shouldHaveSettings: functionApp.Az
686
757
/// <returns>ShouldSyncTrigger value</returns>
687
758
private async Task < bool > HandleFlexConsumptionPublish ( Site functionApp , Func < Task < Stream > > zipFileFactory )
688
759
{
760
+ // Get the WorkerRuntime
761
+ var workerRuntime = GlobalCoreToolsSettings . CurrentWorkerRuntime ;
762
+
763
+ if ( workerRuntime == WorkerRuntime . dotnetIsolated && _requiredNetFrameworkVersion != "8.0" )
764
+ {
765
+ throw new CliException ( $ "You are deploying .NET Isolated { _requiredNetFrameworkVersion } to Flex consumption. Flex consumpton only supports .NET 8. Please upgrade your app to .NET 8 and try the deployment again.") ;
766
+ }
767
+
689
768
Task < DeployStatus > pollDeploymentStatusTask ( HttpClient client ) => KuduLiteDeploymentHelpers . WaitForFlexDeployment ( client , functionApp ) ;
690
769
var deploymentParameters = new Dictionary < string , string > ( ) ;
691
770
@@ -704,7 +783,7 @@ public async Task<DeployStatus> PerformFlexDeployment(Site functionApp, Func<Tas
704
783
using ( var handler = new ProgressMessageHandler ( new HttpClientHandler ( ) ) )
705
784
using ( var client = GetRemoteZipClient ( functionApp , handler ) )
706
785
using ( var request = new HttpRequestMessage ( HttpMethod . Post , new Uri (
707
- $ "api/Deploy/Zip ?isAsync=true&author={ Environment . MachineName } &Deployer=core_tools&{ string . Join ( "&" , deploymentParameters ? . Select ( kvp => $ "{ kvp . Key } ={ kvp . Value } ") ) ?? string . Empty } ", UriKind . Relative ) ) )
786
+ $ "api/publish ?isAsync=true&author={ Environment . MachineName } &Deployer=core_tools&{ string . Join ( "&" , deploymentParameters ? . Select ( kvp => $ "{ kvp . Key } ={ kvp . Value } ") ) ?? string . Empty } ", UriKind . Relative ) ) )
708
787
{
709
788
ColoredConsole . WriteLine ( GetLogMessage ( "Creating archive for current directory..." ) ) ;
710
789
@@ -1141,7 +1220,29 @@ private async Task<bool> PublishLocalAppSettings(Site functionApp, IDictionary<s
1141
1220
1142
1221
private async Task < bool > PublishAppSettings ( Site functionApp , IDictionary < string , string > local , IDictionary < string , string > additional )
1143
1222
{
1223
+ string flexRuntimeName = null ;
1224
+ string flexRuntimeVersion = null ;
1225
+ if ( functionApp . IsFlex )
1226
+ {
1227
+ // if the additiona keys has runtime, it would mean that runtime is already updated.
1228
+ if ( ! additional . ContainsKey ( Constants . FunctionsWorkerRuntime ) )
1229
+ {
1230
+ if ( local . ContainsKey ( Constants . FunctionsWorkerRuntime ) )
1231
+ {
1232
+ flexRuntimeName = local [ Constants . FunctionsWorkerRuntime ] ;
1233
+ local . Remove ( Constants . FunctionsWorkerRuntime ) ;
1234
+ }
1235
+
1236
+ if ( local . ContainsKey ( Constants . FunctionsWorkerRuntimeVersion ) )
1237
+ {
1238
+ flexRuntimeVersion = local [ Constants . FunctionsWorkerRuntimeVersion ] ;
1239
+ local . Remove ( Constants . FunctionsWorkerRuntimeVersion ) ;
1240
+ }
1241
+ }
1242
+ }
1243
+
1144
1244
functionApp . AzureAppSettings = MergeAppSettings ( functionApp . AzureAppSettings , local , additional ) ;
1245
+
1145
1246
var result = await AzureHelper . UpdateFunctionAppAppSettings ( functionApp , AccessToken , ManagementURL ) ;
1146
1247
if ( ! result . IsSuccessful )
1147
1248
{
@@ -1151,6 +1252,12 @@ private async Task<bool> PublishAppSettings(Site functionApp, IDictionary<string
1151
1252
. WriteLine ( ErrorColor ( result . ErrorResult ) ) ;
1152
1253
return false ;
1153
1254
}
1255
+
1256
+ if ( functionApp . IsFlex && ! string . IsNullOrEmpty ( flexRuntimeName ) )
1257
+ {
1258
+ await UpdateRuntimeConfigForFlex ( functionApp , flexRuntimeName , flexRuntimeVersion , new AzureHelperService ( AccessToken , ManagementURL ) ) ;
1259
+ }
1260
+
1154
1261
return true ;
1155
1262
}
1156
1263
@@ -1288,6 +1395,9 @@ public AzureHelperService(string accessToken, string managementUrl)
1288
1395
1289
1396
public virtual Task < HttpResult < string , string > > UpdateWebSettings ( Site functionApp , Dictionary < string , string > updatedSettings ) =>
1290
1397
AzureHelper . UpdateWebSettings ( functionApp , updatedSettings , _accessToken , _managementUrl ) ;
1398
+
1399
+ public virtual Task UpdateFlexRuntime ( Site functionApp , string runtimeName , string runtimeVersion ) =>
1400
+ AzureHelper . UpdateFlexRuntime ( functionApp , runtimeName , runtimeVersion , _accessToken , _managementUrl ) ;
1291
1401
}
1292
1402
1293
1403
private void ShowEolMessage ( FunctionsStacks stacks , WindowsRuntimeSettings currentRuntimeSettings , int ? majorDotnetVersion )
0 commit comments