The fun local command is a subcommand of Funcraft. The fun local command can be run to simulate functions in Function Compute on premises and provides step-by-step debugging. These features enable Function Compute to eliminate the disadvantages in development compared with traditional applications and provide a new troubleshooting method.

Background information

The fun local command provides the fun local invoke and fun local start subcommands. You can run the fun local invoke command to invoke event functions and run the fun local start command to invoke HTTP trigger functions and event functions on premises. You can run the fun local start command in a browser to invoke an HTTP trigger function. When you run the fun local start command to invoke an event function, you can call the InvokeFunction operation or use an SDK to invoke the function. For more information, see InvokeFunction and Supported SDKs.

The fun local command is supported by the graphic plug-ins of different integrated development environments (IDEs), such as Visual Studio Code (VS Code), IntelliJ IDEA, and PyCharm. Compared with command line tools, these plug-ins provide enhanced graphical operations.

  • If you use VS Code, we recommend that you use Aliyun Serverless VSCode Extension. For more information, see Aliyun Serverless VSCode Extension.
  • If you use IntelliJ IDEA or PyCharm, we recommend that you use Alibaba Cloud Toolkit.

Syntax of the fun local invoke command

You can run the fun local invoke -h command to view the help information of the fun local invoke command.
$ fun local invoke -h
  Usage: invoke [options] <[service/]function>

  Run your serverless application locally for quick development & testing.

Options:

   -d, --debug-port <port>  used for local debugging
   -c, --config <ide>       print out ide debug configuration. Options are VSCode
   -e, --event <path>       event file containing event data passed to the function
   -h, --help               output usage information
  • Invoke functions on premises

    The command that is used to invoke functions is in the following syntax:

    fun local invoke [options] <[service/]function>
    The options and service parameters are optional. You can run the fun local invoke command to invoke a function by using the following syntax to specify a function name or both service and function names:
    fun local invoke function
    fun local invoke service/function
    If you need to precisely specify a function, you can specify it in the service/function format.
    Note If the template.yml file contains multiple services, and multiple services contain functions with the same name, only the first function that matches is invoked when you specify a function name.

    Invoke Java functions on premises

    Java is a compiled language. You must compile the code of functions that is written in Java before you invoke the functions. You can use the fun build [function] command to compile the code of a function. For example, run the following command to compile a function named java8:
    fun build java8
    After you run the preceding command, the following log is displayed:
    using template: template.yml
    start building function dependencies without docker
    
    building localdemo/java8
    running task flow MavenTaskFlow
    running task: MavenCompileTask
    running task: MavenCopyDependencies
    running task: CopyMavenArtifacts
    
    Build Success
    Built artifacts: .fun/build/artifacts
    Built template: .fun/build/artifacts/template.yml
    
    Tips for next step======================
    * Invoke Event Function: fun local invoke
    * Invoke Http Function: fun local start
    * Deploy Resources: fun deploy
    After you compile the code of the function, you can run the fun local invoke command to invoke the function.
  • Debug functions on premises

    You can add the -d, --debug-port option to the fun local invoke command to step through a function on premises. The fun local command provides debugging methods that are based on the debugging protocol used by all programming languages. You can use the remote debugging method provided by the programming language that you use.

    • Debug Node.js and Python functions on premises

      Functions that run in Node.js 6, Node.js 8, Python 2.7, Python 3, and Java 8 are debugged in a similar way. Node.js 8 is used in the following example:

      You can run the fun local invoke nodejs8 command to invoke a function named nodejs8. To debug the function, you can add the -d parameter and specify the corresponding port number.

      For example, you can run the following command to set the debug port number to 3000 and debug the function:
      fun local invoke -d 3000 nodejs8
      We recommend that you add the --config parameter to display the IDE configurations used for debugging.
      fun local invoke -d 3000 --config VSCode nodejs8
      The following log is displayed:
      skip pulling images ...
      you can paste these config to .vscode/launch.json, and then attach to your running function
      ///////////////// config begin /////////////////
      {    
        "version": "0.2.0",    
        "configurations": [
              {
                  "name": "fc/localdemo/nodejs8",
                  "type": "node",
                  "request": "attach",
                  "address": "localhost",
                  "port": 3000,
                  "localRoot": "/Users/tan/code/fun/examples/local/nodejs8",
                  "remoteRoot": "/code",
                  "protocol": "inspect",
                  "stopOnEntry": false
              }
          ]
      }
      ///////////////// config end /////////////////
      Debugger listening on ws://0.0.0.0:3000/b65c288b-bd6a-4791-849b-b03e0d16b0ce
      For help see https://nodejs.org/en/docs/inspector
      The function is blocked and continues to be executed only after you configure the IDE. The following part describes how to configure VS Code and debug functions in VS Code:

      The VS Code configuration is required only when you debug functions for the first time. If you have configured VS Code, you do not need to configure VS Code again.

      1. Configure VS Code.
        1. Create a launch.json file in VS Code.vscode_config
        2. Copy the configurations that are displayed between the config begin and config end comments in the preceding log to the launch.json file.config_copy
        3. Find the function in the DEBUG drop-down list.copy_config_success

          VS Code configuration is complete. For more information about VS Code configuration, visit Debugging.

      2. Debug functions in VS Code
        1. After VS Code is configured, you can click the editor margin to create breakpoints and click the Start Debugging icon.vscode_debbugging
        2. The following example shows how to step through the function named nodejs8 on premises.funlocal_debugging
    • Debug Java functions on premises
      • Debug Java functions in VS Code

        You must install the Language Support for Java™ by Red Hat and Debugger for Java plug-ins before you debug Java functions in VS Code. For more information about how to install plug-ins in the VS Code marketplace, visit Java in Visual Studio Code.

        The following example shows how to debug a Java function in VS Code.

        vscode_java
      • Debug Java functions in IntelliJ IDEA
        In the top navigation bar, choose Run > Edit Configurations.... IDEA_config
        1. Click the Create icon and select Remote to create a remote debug configuration.debugging_creat
        2. Enter a name in the Name field and set the port number to 3000.config_port
        3. The following example shows how to configure remote debugging in IntelliJ IDEA.config_IDEA_gif
      • Debug functions in IntelliJ IDEA
        Run the following command to invoke and debug a Java function:
        fun local invoke -d 3000 java8
        java_debug

        The function is blocked. You must configure IntelliJ IDEA to start debugging. Choose Run > Debug… in the top navigation bar or click the Debug icon in the tool bar to start debugging.

        The following example shows how to perform remote debugging in IntelliJ IDEA. IDEA_remote debugging
  • Debug PHP functions on premises

    The process of debugging PHP functions is different from that of debugging other types of functions.

    PHP functions are invoked by running the fun local invoke php72 command and debugged by adding the -d parameter, in the same manner as other types of functions.
    fun local invoke -d 3000 --config VSCode php72
    However, when you invoke and debug a PHP function, the PHP function is not blocked and does not wait for the VS Code debugger to connect.
    skip pulling images ...
    you can paste these config to .vscode/launch.json, and then attach to your running function
    ///////////////// config begin /////////////////
    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "fc/localdemo/php72",
                "type": "php",
                "request": "launch",
                "port": 3000,
                "stopOnEntry": false,
                "pathMappings": {
                    "/code": "/Users/tan/code/fun/examples/local/php7.2"
                },
                "ignore": [
                    "/var/fc/runtime/**"
                ]
            }
        ]
    }
    ///////////////// config end /////////////////
    FunctionCompute php7.2 runtime inited.
    FC Invoke Start RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4
    FC Invoke End RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4
    hello world
    RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4          Billed Duration: 48 ms          Memory Size: 1998 MB        Max Memory Used: 58 MB

    This is because you must first start the VS Code debugger for PHP functions.

    The process of starting the VS Code debugger for PHP functions is the same as that for other types of functions: You must copy the configurations in the preceding log to the launch.json file and click the Start Debugging icon. Then, you can invoke the PHP function in debugging mode and debug the function on the terminal.
    fun local invoke -d 3000 php72
    php_config
  • Construct trigger events

    Function Compute provides various triggers, such as Object Storage Service (OSS) triggers, Log Service triggers, and Alibaba Cloud CDN event triggers. To simulate the Function Compute environment, you must construct trigger events when you invoke or debug functions on premises.

    A trigger event can be readable JSON configurations or non-readable binary data. The following example shows a JSON event:
    {
        "testKey": "testValue"
    }
    You can use one of the following methods to pass the event to your function:
    • Pipe: echo '{"testKey": "testValue"}' | fun local invoke nodejs8
    • File: Create a JSON file, such as event.json, to store the JSON event. Use the -e parameter to specify the file name in the command: fun local invoke -e event.json nodejs8.
    • Redirection: fun local invoke nodejs8 < event.json or fun local invoke nodejs8 <<< '{"testKey": "testValue"}'. For more information, visit Bash Input Redirection.

fun local start

You can run the fun local invoke -h command to view the help information of the fun local invoke command.
Usage: fun local start [options]

    Allows you to run the Function Compute application locally for quick development & testing.
    It will start an http server locally to receive requests for http triggers and apis.
    It scans all functions in template.yml. If the resource type is HTTP, it will be registered to this http server, which can be triggered by the browser or some http tools.
    For other types of functions, they will be registered as apis, which can be called by sdk in each language or directly via api.

    Function Compute will look up the code by CodeUri in template.yml.
    For interpreted languages, such as node, python, php, the modified code will take effect immediately, without restarting the http server.
    For compiled languages ​​such as Java, we recommend you set CodeUri to the compiled or packaged location.
    Once compiled or packaged result changed, the modified code will take effect without restarting the http server.

  Options:

    -d, --debug-port <port>      specify the sandboxed container starting in debug mode, and exposing this port on localhost
    -c, --config <ide/debugger>  output ide debug configuration. Options are vscode
    -h, --help                   output usage information
  • Invoke HTTP trigger functions on premises
    Run the following command:
    fun local start [options]

    The options parameter is optional.

    After you run the fun local start command, Funcraft starts an HTTP server to provide HTTP services. Then, Funcraft registers functions that are described in the template.yml file and configured with HTTP triggers at the HTTP server. After the registration, you can trigger the functions by using HTTP tools, such as browsers.

    For example, all HTTP trigger information is displayed after you run the fun local start command in the local_http path: http_triggerYou can trigger an HTTP trigger function by using the corresponding URL.
    The following example shows how to trigger an HTTP trigger function in Node.js. The process also applies to Python and PHP. nodejs http trigger
  • Debug HTTP trigger functions on premises

    You can add the -d, --debug-port option to debug HTTP trigger functions on premises. The process is similar to the process of using events to trigger functions. You can also add the -c, --config option to display the IDE configurations.

    Run the fun local start --debug 3000 --config vscode command to start a service. The following result shows that all the functions described in the template.yml file are registered. Http TriggerSelect a URL based on the service name, function name, or HTTP trigger name and open the URL by using a browser. The browser generates no responses, and the terminal displays the following log:
    skip pulling image aliyunfc/runtime-python3.6:1.2.0...
    you can paste these config to .vscode/launch.json, and then attach to your running function
    ///////////////// config begin /////////////////
    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "fc/local-http-demo/python3",
                "type": "python",
                "request": "attach",
                "host": "localhost",
                "port": 3000,
                "pathMappings": [
                    {
                        "localRoot": "/Users/tan/fun_local_http_demo/python3",
                        "remoteRoot": "/code"
                    }
                ]
            }
        ]
    }
    ///////////////// config end /////////////////
    FunctionCompute python3 runtime inited.
    FC Invoke Start RequestId: 04c57fba-cbe9-4c1f-8c57-f8e0b539fa08
    Copy the configurations in the preceding log to the VS Code debugger, create breakpoints, and click the Start Debugging icon.
    The following example shows how to debug an HTTP trigger function in Python. This process also applies to Node.js and PHP. python http trigger
  • Perform a hot load

    A hot load is performed when you invoke and debug HTTP trigger functions on premises.

    Assume that you have started an on-premises service by running the fun local start command and modified the code of a function. In this case, you can refresh the web page or trigger the function again to invoke the modified function without the need to reload the on-premises service.

    The following example shows the hot load result of a Node.js function. This process also applies to PHP and Python functions. You must run the npm install command in the function directory in advance to initialize the Node.js modules on which the function depends.

  • Call API operations to invoke and debug functions on premises
    The command syntax is the same as that used to invoke an HTTP trigger function.
    fun local start [options]

    The options parameter is optional.

    After you run the fun local start command, Funcraft starts an HTTP server to provide HTTP services. Then, Funcraft registers functions that are described in the template.yml file and not configured with HTTP triggers at the HTTP server. After the registration, you can call the InvokeFunction operation or use SDKs to invoke the functions. For more information, see List of operations by function and Supported SDKs.

    If you invoke the functions by calling API operations, signature authentication is required.We recommend that you use SDKs to invoke functions. Run the fun local start command to run a service. The following log is displayed:
    $ fun local start
    
    api localdemo/php72 was registered
        url: http://localhost:8000/2016-08-15/services/localdemo/functions/php72/invocations/
    api localdemo/python27 was registered
        url: http://localhost:8000/2016-08-15/services/localdemo/functions/python27/invocations/
    api localdemo/python3 was registered
        url: http://localhost:8000/2016-08-15/services/localdemo/functions/python3/invocations/
    api localdemo/nodejs6 was registered
        url: http://localhost:8000/2016-08-15/services/localdemo/functions/nodejs6/invocations/
    api localdemo/nodejs8 was registered
        url: http://localhost:8000/2016-08-15/services/localdemo/functions/nodejs8/invocations/
    api localdemo/java8 was registered
        url: http://localhost:8000/2016-08-15/services/localdemo/functions/java8/invocations/
    function compute app listening on port 8000!
    After the service is started, you can use SDK for Python to invoke functions.
    Run the following command to install Function Compute SDK for Python:
    pip install aliyun-fc2
    Enter the following code:
    import fc2
    
    client = fc2.Client(endpoint='http://localhost:8000', accessKeyID='<your access key id>', accessKeySecret='your access key secret')
    
    resp = client.invoke_function('localdemo', 'php72')
    
    print resp.headers
    print resp.data
    Note The AccessKey ID and AccessKey secret configured in the SDK code must be the same as those in Funcraft. Otherwise, signature authentication fails when you invoke functions.
    The following figure shows the running result. config

Other operations

  • Run the fun local invoke command to access a service on the host
    If you use Docker 18.03 or later for macOS or Windows, you can use host.docker.internal as the IP address to access your on-premises service. For example, you can run the following command:
    client = fc2.Client(endpoint='http://host.docker.internal:8000', accessKeyID='xxx', accessKeySecret='xxx')
     resp = client.invoke_function('localdemo', 'nodejs8', json.dumps({'code': 123}))
    If you use a version earlier than Docker 18.03, you can run the ifconfig command for Linux or macOS or the ipconfig command for Windows on the host to view the host IP address and configure the IP address to the endpoint.
  • Use environment variables

    Environment variables configured in the template.yml file are the same as those in Function Compute. You can run code to obtain the environment variables when functions are executed. For more information, see Configure environment variables.

    You can determine whether a function is invoked on premises or in Function Compute based on the environment variables for specific logic processing.

  • Credentials

    You can use the AccessKey pair that is stored in credentials to access other Alibaba Cloud services. The fun local and fun deploy commands use the same method to search for the AccessKey pair.

    For more information about Function Compute credentials, see the following sample code.

    The following code provides an example on how to configure an OSS client by using credentials on premises and in Function Compute:
    local = bool(os.getenv('local', ""))
    if (local):
        print 'thank you for running function in local!!!!!!'
        auth = oss2.Auth(creds.access_key_id,
                         creds.access_key_secret)
    else:
        auth = oss2.StsAuth(creds.access_key_id,
                            creds.access_key_secret,
                            creds.security_token)