Thursday, 4 October 2018

3 ways to create and debug Azure Functions – CLI, VS Code and Visual Studio

Recently I’ve been thinking about different ways to work Azure Functions, and the pros and cons of each. I wanted to better understand the Azure Functions Core Tools (also known as the CLI), and that role that plays in developing functions locally and then publishing them to Azure. I’d recently seen a Microsoft guy use this in his demos, and I was wondering if I was missing an important aspect of Azure Functions (which I try to stay on top of). Between Visual Studio Code/full Visual Studio/the command-line approach with the Core Tools, there’s a lot of overlap – so which is best when?

Things you should be aware of when developing with Azure Functions:

  Azure Functions v2:
Microsoft have recently launched v2 of Azure Functions, which has some differences around bindings, runtime behaviour and performance. However, if you’re an Office 365/SharePoint person, note that at this time (October 2018), you need to stay with v1 for C# functions if you want to use CSOM or PnP. This is because we don’t yet have a .NET Core version of these packages – and v2 runs on .NET Core. So, you’ll get errors if you try to build functions using v2 if you try to use these packages. Hopefully we won’t have to wait too long though – see https://twitter.com/vesajuvonen/status/1045668458971766784

  The Azure Functions Core Tools/CLI:
Although I talk about 3 options for developing/publishing functions here, in fact the Core Tools are a pre-requisite for all of them. Whether you choose to use Visual Studio Code or full Visual Studio to write your code, *debugging* is handled by the Core Tools in all cases. I note the installation process in the “option 1” section below..

OK, back to the development options. First let’s be clear on what the process looks like with each.

Option 1 - with Azure Functions Core Tools/CLI

The command-line approach can be interesting because it’s the same across platforms, although to be fair it’s currently only version 2 of Azure Functions which can be used across macOS and Linux. But what you get here is the ability to:

  • Create your function
  • Run it locally
  • Deploy to a Function App in Azure 

PRE-REQS:

  • Ensure you have .NET and node.js installed on your machine (for npm)
  • Install Azure Functions Core Tools using npm install -g azure-functions-core-tools@core
  • See Install the Azure Functions Core Tools for more info

PROCESS:

We’ll create a simple HTTP function in JavaScript in this case. As you might expect, we run commands at the command-line to create new functions and work with them.

    1. Create a folder for the function you’ll create, and open a command prompt there.
    2. Type func init to initalize the folder with the files needed for an Azure Function:

      SNAGHTML89c0d7c
    3. To create a function, type func new to start the process. In V1 functions, you’ll need to provide:
      1. The language
      2. The trigger
               
        SNAGHTML875154a
    4. Provide a name for your function:       
            
      SNAGHTML8763197
      1. Now open the function folder in VS Code (you do know about the “code .” command to open to the current directory right?):

        SNAGHTML8637786
        1. <VS Code opens>
          1. If you have the VS Code extension for Azure Functions installed, you’ll see this:

            SNAGHTML8652b31

            This is basically asking you if you’d like to switch to the VS Code way of doing things. For now, we’ll close this message to work with the command-line/Core Tools experience.

            1. Now you can add code to your function as needed.
            2. Now type func run <Your function name> to run the function locally –the first time you do this, you’ll see this message that we need to OK:

              SNAGHTML549c85
            3. In the case of a HTTP function like this, we should pass some content in the POST body using the --content flag. To match up with the default code that the generator added, let’s pass some JSON including a ‘name’ attribute:

              SNAGHTML5facdb
            4. You should now see the functions runtime spin up and serve your function:

              SNAGHTML1d491eb
            5. Since your function is being served on a local endpoint, you’ll most likely want to use Postman or similar as you develop the code (as per the earlier recommendation) since this is much richer than the --content flag. The output from the Core Tools will tell you the URL to hit, but by default it is http://localhost:7071/api/[function name]:

              SNAGHTML1dd8740

            Publishing the (JavaScript) function using the CLI and Visual Studio Code

              After developing the code some more, we can deploy directly to a Function App in Azure with other commands. Most likely you’ll need to login first, and this is done with the following command:

              func azure login --username [username] --password [password]

              If you don’t provide a username/password, you’ll be prompted interactively:

              SNAGHTML1e4d89b

              You may need to explicitly choose the Azure subscription (once you’ve signed-in) with this command, for example if that account has access to multiple subscriptions:

              func azure account set [AzureSubscriptionID]

              From here you can use the following to deploy the function:

              func azure functionapp publish <FunctionAppName>

              SNAGHTMLcb421e

              This is great, but something is missing – debugging!

              Debugging the (JavaScript) function using the CLI and Visual Studio Code

              At first I thought it wasn’t possible to debug functions locally using the CLI, but it is by combining it with VS Code. The process is:

              • Put a breakpoint in your code in VS Code
              • Run your function from the CLI and add the --debug flag – so func run <Your function name> –debug
              • Hit F5 (or go to the Debug tab and press Play)
              • Make a request to your function’s local URL e.g. http://localhost:7071/api/[function name]:
              • Your breakpoint will now be hit and you can make use of all of VS Code’s debugging capabilities:

                     SNAGHTMLd45210
              NOTE:- debugging C# functions isn't quite this simple in VS Code. See my section later on this.
              So the CLI isn't useful on it's own?
              At this point, you might be wondering why you'd work with Azure Functions using the CLI if you need to use Visual Studio Code to debug. Me too! The Azure Functions extension for VS Code is essentially running the commands against the CLI for you, and gives you some menu options/commands in the command pallette to work with, thus providing a much nicer experience. For me, the only scenarios where you'd focus on the CLI for running/publishing functions are:
              • DevOps scenarios, where you have some automation scripts to run/test your functions (either locally or by deploying them up to Azure)
              • You're trying to be ultra-hip
              For everything else, there's Visual Studio Code or Visual Studio. Disagree? Am I missing something? Let me know in the comments!

              Option 2 – with Visual Studio Code

              PRE-REQS:

              PROCESS:

              Creating a function in VS Code is easy:

              1. First, create a folder on your machine to host the files – I named my folder “COB-JS-Functions” to reflect what we’re doing here.
              2. Open VS Code to this folder.
              3. Hit CTRL SHIFT + P for the VS Code command bar, and start typing “Azure Functions” to pull up those commands. Select the “Create New Project” command:
                SNAGHTMLfff7b5_thumb2
              4. Follow the prompts in the command bar to select the folder – accept the default if you’re already in the folder you created earlier:
                SNAGHTML1568088c_thumb2
              5.     
              6. When it comes to selecting a language, select your preference – I’m using JavaScript here (and you might want to consider my overall message that C# functions are generally easier in full-blown Visual Studio!):
                SNAGHTML1569e4bf_thumb2
              7. Your folder will now be scaffolded with the starter files:

                SNAGHTML45dc105
              8. Now let’s add an individual function. Hit CTRL SHIFT + P again, and find the “Create Function” command under Azure Functions:
                SNAGHTML156d23fb_thumb3
              9. Accept that we’ll use the current folder:
                SNAGHTML462a5c4
              10.   Select the trigger:
                SNAGHTML463eb15
              11. Enter the name for your function:
                SNAGHTML4654ae3
              12. And then the authentication type:
                SNAGHTML469c32d 
              13. A bunch of new files will now be added to your folder, including the “index.js” file for your function implementation:
                SNAGHTML46ae3d0

              You can now code away and start to build out your function. Most likely you’ll want to bring in some npm modules for a JavaScript function, and start to work against the Graph, SharePoint or whatever you need. I really like being guided through the process through the VS Code command palette, I think it works really well.

              Debugging Azure Functions locally in Visual Studio Code

              VS Code works great as a debugger for JavaScript functions, PowerShell scripts and more. The next sections have a couple of notes on language-specific details:

              For JavaScript Functions 

              JavaScript mainly “just works”, although you’ll need to hit the local URL your function is hosted on (e.g. with Postman or similar) by default. You can go a step further and amend your launch.json file so that F5 does everything - I had to add a configuration for ‘launch’ as well as ‘attach’. The process looks like this:

              1. Add a breakpoint to your code.
              2. Once your launch.json is good, ensure you have a “launch” configuration selected in the debug config selector – this ensures node.js is started, rather than assuming it’s running already and you can attach to it:
                SNAGHTML17b668d7
              3. You should see VS Code spin up the functions host for you by running func host start:

                SNAGHTML17bc75e9
              4. You’ll actually need to hit the URL for your function to start the execution and hit your breakpoint. VS Code makes this easy by providing a clickable link in the terminal output:
                SNAGHTML17bdf98c
              5. This will open a new browser tab, hit your function endpoint, and your breakpoint will be hit
              For PowerShell Functions

              See my “Running a PowerShell script in the cloud with an Azure Function, PnP and the Graph” article, specifically the “Debugging our PowerShell script locally with F5” section – I show the process in detail here. In short it works well, but remember that PowerShell only has experimental language status in Functions V1, and this did not go forward into V2.

              For C# Functions

              Well, debugging C# functions which are .cs files (not .csx) in Visual Studio Code is somewhat different – the OmniSharp extension is required (https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp) and there is some shennanigans involved to debug V1 functions since they are 32-bit. See https://github.com/Microsoft/vscode-azurefunctions/blob/master/docs/func64bit.md. Overall I feel that full Visual Studio is a simpler approach for C# functions.

              Publishing files to an Azure Function from VS Code:

              In the spirit of re-use, this section comes straight from my PowerShell functions article :) The steps here are the same regardless of your function language.

              You can publish your function to Azure in a variety of ways, but VS Code makes this easy:

              1. Switch to Azure tab in VS Code (bottom icon):

                SNAGHTMLbf4881_thumb2
              2. Find the Function App you created earlier. Right-click on it, and select “Deploy to Function App”:
                SNAGHTML1ea4112d_thumb2
              3. Step through prompts in the VS Code command palette – the defaults are generally what you need:

                SNAGHTMLc1f726_thumb2
              4. Accept the prompt:

                image_thumb4

              5. VS Code will then start the publish operation:

                SNAGHTMLc9b489_thumb2
              6. You’ll then find that your files have been deployed as a Function to the selected Function App:

                SNAGHTMLe32952_thumb2

              Option 3 – using Visual Studio

              Visual Studio is my preferred option for C# functions (for the moment at least).

              PRE-REQS:

              PROCESS:

              There is a VS project template, so creating a new project is easy:

              1. Create a new project using Create > New Project:
                SNAGHTML96f93a2
              2. Add a new Function from the context menu on the project:
                SNAGHTML5722ec4
                Select the trigger type:
                SNAGHTML9712f70

              Debugging a function in Visual Studio:

              This is as simple as adding a breakpoint and hitting F5. For C# functions, as things stand this is much simpler than the other options. You’ll see the Core Tools function host spin-up, and the URL of your function will be provided – you’ll need to hit this in a browser or with Postman, although you could configure the “Debug” tab of your project to launch a browser or script to do this automatically (similar to the idea of editing the launch.json file if using Visual Studio Code):

              SNAGHTML9755aa3

              Your breakpoint will then be hit:

              SNAGHTML97ba6a3

              Remember that you can also debug a function running live in Azure if it was published in debug mode. If you’re developing against a dev/test Office 365 tenant and Azure subscription this can be very helpful (but not recommended for production obviously). Use the Cloud Explorer to find your function, right-click and select “Debug”.

              Publishing a function from Visual Studio

              Anyone who’s worked with functions in VS is probably familiar with this, but as you’d expect it’s a slick experience:

              SNAGHTML9a1600c

              SNAGHTML9a23c14

              But as the saying goes, friends don’t let friends publish Azure Functions directly to production (and potentially other environments too). Use one of the other deployment methods, perhaps one based on continuous deployment if appropriate. 

              Summary

              That was quite a lot detail. In summary, if you write the majority of your other code with VS Code and/or are writing functions in JavaScript, then VS Code is probably your best choice – just make sure you install the Azure Functions VS Code extension. If you’re mainly using full Visual Studio, then stick with that for functions development too – just make sure you install the Azure Functions Visual Studio extension if your VS instance doesn’t have it already.

              Using the Core Tools directly from the command-line is best-suited to CI/CD/DevOps automation, or those who feel the need to be particularly hipster.