Skip to content

Commit

Permalink
Check if bundle config exists, hostJson exists (#1882)
Browse files Browse the repository at this point in the history
  • Loading branch information
soninaren authored Mar 8, 2020
1 parent a4e2578 commit d8d237f
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/Azure.Functions.Cli/Actions/HostActions/StartHostAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Azure.WebJobs.Script.Description;

namespace Azure.Functions.Cli.Actions.HostActions
{
Expand Down Expand Up @@ -248,6 +249,7 @@ public override async Task RunAsync()
await PreRunConditions();
Utilities.PrintLogo();
Utilities.PrintVersion();
ValidateHostJsonConfiguration();

var settings = SelfHostWebHostSettingsFactory.Create(Environment.CurrentDirectory);

Expand All @@ -268,6 +270,21 @@ public override async Task RunAsync()
await runTask;
}

private void ValidateHostJsonConfiguration()
{
bool IsPreCompiledApp = IsPreCompiledFunctionApp();
var hostJsonPath = Path.Combine(Environment.CurrentDirectory, Constants.HostJsonFileName);
if (IsPreCompiledApp && !File.Exists(hostJsonPath))
{
throw new CliException($"Host.json file in missing. Please make sure host.json file is preset at {Environment.CurrentDirectory}");
}

if (IsPreCompiledApp && BundleConfigurationExists(hostJsonPath))
{
throw new CliException($"Extension bundle configuration should not be present for the function app with pre-compiled functions. Please remove extension bundle configuration from host.json: {Path.Combine(Environment.CurrentDirectory, "host.json")}");
}
}

private async Task PreRunConditions()
{
if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python)
Expand Down Expand Up @@ -301,6 +318,33 @@ private async Task PreRunConditions()
}
}

private bool BundleConfigurationExists(string hostJsonPath)
{
var hostJson = FileSystemHelpers.ReadAllTextFromFile(hostJsonPath);
return hostJson.Contains(Constants.ExtensionBundleConfigPropertyName, StringComparison.OrdinalIgnoreCase);
}

private bool IsPreCompiledFunctionApp()
{
bool isPrecompiled = false;
foreach (var directory in FileSystemHelpers.GetDirectories(Environment.CurrentDirectory))
{
var functionMetadataFile = Path.Combine(directory, Constants.FunctionJsonFileName);
if (File.Exists(functionMetadataFile))
{
var functionMetadataFileContent = FileSystemHelpers.ReadAllTextFromFile(functionMetadataFile);
var functionMetadata = JsonConvert.DeserializeObject<FunctionMetadata>(functionMetadataFileContent);
string extension = Path.GetExtension(functionMetadata?.ScriptFile)?.ToLowerInvariant().TrimStart('.');
isPrecompiled = isPrecompiled || (!string.IsNullOrEmpty(extension) && extension == "dll");
}
if (isPrecompiled)
{
break;
}
}
return isPrecompiled;
}

private void DisplayDisabledFunctions(IScriptJobHost scriptHost)
{
if (scriptHost != null)
Expand Down
2 changes: 2 additions & 0 deletions src/Azure.Functions.Cli/Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal static class Constants
public const string FunctionsWorkerRuntimeVersion = "FUNCTIONS_WORKER_RUNTIME_VERSION";
public const string RequirementsTxt = "requirements.txt";
public const string FunctionJsonFileName = "function.json";
public const string HostJsonFileName = "host.json";
public const string ExtenstionsCsProjFile = "extensions.csproj";
public const string DefaultVEnvName = "worker_env";
public const string ExternalPythonPackages = ".python_packages";
Expand All @@ -45,6 +46,7 @@ internal static class Constants
public const string DefaultManagementURL = "https://management.azure.com/";
public const string AzureManagementAccessToken = "AZURE_MANAGEMENT_ACCESS_TOKEN";
public const string AzureFunctionsEnvorinmentEnvironmentVariable = "AZURE_FUNCTIONS_ENVIRONMENT";
public const string ExtensionBundleConfigPropertyName = "extensionBundle";
public const string AspNetCoreEnvironmentEnvironmentVariable = "ASPNETCORE_ENVIRONMENT";

public static string CliVersion => typeof(Constants).GetTypeInfo().Assembly.GetName().Version.ToString(3);
Expand Down
70 changes: 70 additions & 0 deletions test/Azure.Functions.Cli.Tests/E2E/StartTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,76 @@ await CliTester.Run(new RunConfiguration[]
}, _output);
}

[Fact]
public async Task start_displays_error_on_invalid_host_json()
{
var functionName = "HttpTriggerCSharp";

await CliTester.Run(new RunConfiguration[]
{
new RunConfiguration
{
Commands = new[]
{
"init . --worker-runtime dotnet",
$"new --template Httptrigger --name {functionName}",

},
Test = async (workingDir, p) =>
{
var filePath = Path.Combine(workingDir, "host.json");
string hostJsonContent = "{ \"version\": \"2.0\", \"extensionBundle\": { \"id\": \"Microsoft.Azure.Functions.ExtensionBundle\", \"version\": \"[1.*, 2.0.0)\" }}";
await File.WriteAllTextAsync(filePath, hostJsonContent);
},
},
new RunConfiguration
{
Commands = new[]
{
"start"
},
ExpectExit = true,
ExitInError = true,
ErrorContains = new[] { "Extension bundle configuration should not be present" },
},
}, _output, startHost: true);
}


[Fact]
public async Task start_displays_error_on_missing_host_json()
{
var functionName = "HttpTriggerCSharp";

await CliTester.Run(new RunConfiguration[]
{
new RunConfiguration
{
Commands = new[]
{
"init . --worker-runtime dotnet",
$"new --template Httptrigger --name {functionName}",
},
Test = async (workingDir, p) =>
{
var hostJsonPath = Path.Combine(workingDir, "host.json");
File.Delete(hostJsonPath);

},
},
new RunConfiguration
{
Commands = new[]
{
"start"
},
ExpectExit = true,
ExitInError = true,
ErrorContains = new[] { "Host.json file in missing" },
},
}, _output);
}

[Fact]
public async Task start_host_port_in_use()
{
Expand Down

0 comments on commit d8d237f

Please sign in to comment.