Azure / azure-functions-core-tools

Command line tools for Azure Functions
MIT License
1.32k stars 434 forks source link

[Bug] func host start should continue with the best available ExtensionBundle version when internet connectivity isn't available #3274

Open mbartenschlag opened 1 year ago

mbartenschlag commented 1 year ago

The func host start command unnecessarily fails when not connected to the internet. This is trivial to reproduce:

  1. Install the Azure Functions Core Tools 4.
  2. Create a new directory.
  3. Run func new --name "HttpTrigger" --template "HTTP Trigger" within that directory. Choose python when prompted.
  4. Start the function using func host start --verbose while connected to the internet.
  5. Stop the function.
  6. Disconnect from the internet.
  7. Run func host start --verbose again.

While disconnected from the internet, the second func host start fails even though the function has everything it needs to run locally. The specific issue is that even though a version of the Microsoft.Azure.Functions.ExtensionBundle is found, a call goes out to https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/index.json anyway to see if the found version is the latest version.

This is shown in the logs below. In the first execution of func host start --verbose, we see:

[2023-02-17T01:04:24.299Z] Looking for extension bundle Microsoft.Azure.Functions.ExtensionBundle at /home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle
[2023-02-17T01:04:24.299Z] Found a matching extension bundle at /home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/3.17.0
[2023-02-17T01:04:24.299Z] Fetching information on versions of extension bundle Microsoft.Azure.Functions.ExtensionBundle available on https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/index.json
[2023-02-17T01:04:24.421Z] Skipping bundle download since it already exists at path /home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/3.17.0
[2023-02-17T01:04:24.426Z] Loading extension bundle from /home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/3.17.0/bin
[2023-02-17T01:04:24.426Z] Script Startup resetting load context with base path: '/home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/3.17.0/bin'.

After disconnecting from the internet, we get:

[2023-02-17T01:11:09.839Z] Looking for extension bundle Microsoft.Azure.Functions.ExtensionBundle at /home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle
[2023-02-17T01:11:09.839Z] Found a matching extension bundle at /home/matthewb/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/3.17.0
[2023-02-17T01:11:09.839Z] Fetching information on versions of extension bundle Microsoft.Azure.Functions.ExtensionBundle available on https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/index.json
[2023-02-17T01:11:19.857Z] A host error has occurred during startup operation '4eb2bce5-5473-49d7-a067-ed9a4b050a40'.
[2023-02-17T01:11:19.857Z] System.Net.Http: Resource temporarily unavailable (functionscdn.azureedge.net:443). System.Net.Sockets: Resource temporarily unavailable.
[2023-02-17T01:11:19.903Z] Initialization cancellation requested by runtime.
[2023-02-17T01:11:19.907Z] Stopping host...
[2023-02-17T01:11:19.908Z] Host shutdown completed.

This is a bug based on a bad assumption - not all development and test environments are connected to the internet. If a matching version of the ExtensionBundle is found, failing to determine if the found version is the latest version should emit a warning if internet connectivity is unavailable.

Version information provided below:

matthewb@DESKTOP-xxx:~/workspace/azure-simple$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.5 LTS
Release:        20.04
Codename:       focal
matthewb@DESKTOP-xxx:~/workspace/azure-simple$ func --version
4.0.4895
matthewb@DESKTOP-xxx:~/workspace/azure-simple$ uname --all
Linux DESKTOP-xxx 5.10.102.1-microsoft-standard-WSL2 #1 SMP Wed Mar 2 00:30:59 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Attempted Workarounds

Removing the bundle from host.json is not an option because the real-world scenario involves durable functions where the bindings provided by the bundle are required. Manually including the extensions via the Azure Core Tools CLI is not an option as that attempts to reach out to nuget.org. ❌ Specifying "version": "=3.17.0" or version": "==3.17.0" in host.json prior to func host start fails as those values are recognized as invalid. ❌ Specifying "version": "3.17.0" in host.json instead of a version range prior to startup surprisingly attempts to retrieve version 4.0.2 of the bundle without error or warning. This may be a bug - I haven't looked at the documentation for this value. ❌ Specifying "version": "[3.17.0, 3.17.0]" in host.json after that version has already been downloaded does not prevent latest version checks - even though it already found the exact version we wanted.

RichieRock commented 1 year ago

Any update on this?

I am often developing locally without an internet connection and can not run the functions at all (I have to wait until connection comes back online). From a developer's point of view it would be nice to use the already downloaded extension bundles that I have already installed on my machine and not completely fail when trying to get the latest online.

Hoping this gets fixed :)

wtcooper commented 1 year ago

Hi all,

I agree a solution is needed, I can't test locally while traveling. Any updates?

offbeatful commented 1 year ago

So for anyone who is looking for a solution to run their functions without Internet access:

I was required to remove extensionBundle section from host.json file. Why does this work?

It seems there is a code introduced in src/Azure.Functions.Cli/Actions/HostActions/Startup.cs that will check if extensionBundle is defined and if it is, it will set environment variables to check for latest version.

private void SetBundlesEnvironmentVariables()
{
    var bundleId = ExtensionBundleHelper.GetExtensionBundleOptions(_hostOptions).Id;
    if (!string.IsNullOrEmpty(bundleId))
    {
        Environment.SetEnvironmentVariable("AzureFunctionsJobHost__extensionBundle__downloadPath", ExtensionBundleHelper.GetBundleDownloadPath(bundleId));
        Environment.SetEnvironmentVariable("AzureFunctionsJobHost__extensionBundle__ensureLatest", "true");
    }
}

That code was actually introduced as part of another issues:

  // workaround for https://github.com/Azure/azure-functions-core-tools/issues/2097
  SetBundlesEnvironmentVariables();

I am running javascript functions and I confirmed that this section is not required for Development Model 4 when deploying in Azure. So extensionBundle section can be safely removed.