12/05 Azure Functions with Serverless Framework

Serverless Hello World Advent Calendar 2020째 날이다.
Serverless Framework에 Azure Function의 HTTP API를 설치합니다.
아래 참조Azure Functions - Quickstart로 소개합니다.

Serverless Framerowk 가져오기

npm에 전 세계serverless에 가입하면 됩니다.

서비스 작성


$ sls create -t azure-nodejs -p helloworld
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/home/masa/work/serverless-helloworld/05/helloworld"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v2.15.0
 -------'

Serverless: Successfully generated boilerplate for template: "azure-nodejs"
$ cd 05/helloworld
$ npm install

생성된 파일 확인

serverless.yml에 두 개의 함수가 등록되어 있다.
service: helloworld

frameworkVersion: '2'

provider:
  name: azure
  region: West US 2
  runtime: nodejs12

  environment: # these will be created as application settings
    VARIABLE_FOO: 'foo'

plugins: # look for additional plugins in the community plugins repo: https://github.com/serverless/plugins
  - serverless-azure-functions

package:
  exclude:
    - local.settings.json
    - .vscode/**

functions:
  hello:
    handler: src/handlers/hello.sayHello
    events:
      - http: true
        methods:
          - GET
        authLevel: anonymous # can also be `function` or `admin`

  goodbye:
    handler: src/handlers/goodbye.sayGoodbye
    events:
      - http: true
        methods:
          - GET
        authLevel: anonymous
src/handlers/hello.js는 함수의 주체다.
'use strict';

module.exports.sayHello = async function(context, req) {
  context.log('JavaScript HTTP trigger function processed a request.');

  if (req.query.name || (req.body && req.body.name)) {
    context.res = {
      // status: 200, /* Defaults to 200 */
      body: 'Hello ' + (req.query.name || req.body.name),
    };
  } else {
    context.res = {
      status: 400,
      body: 'Please pass a name on the query string or in the request body',
    };
  }
};

로컬 환경에서의 작업 확인

sls offline의 로컬 환경에서 함수 프로그램을 실행해 봅니다.
$ sls offline
Serverless: Initializing provider configuration...
Serverless: Configuration warning: Unrecognized provider 'azure'
Serverless:  
Serverless: You're relying on provider plugin which doesn't provide a validation schema for its config.
Serverless: Please report the issue at its bug tracker linking: https://www.serverless.com/framework/docs/providers/aws/guide/plugins#extending-validation-schema
Serverless: You may turn off this message with "configValidationMode: off" setting
Serverless:  
Serverless: Building offline service
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: hello event: httpTrigger
Serverless: Building binding for function: goodbye event: httpTrigger
Serverless: Finished building offline service
Serverless: undefined
Serverless: Spawning process 'func host start'

Azure Functions Core Tools
Core Tools Version:       3.0.3160 Commit hash: 00aa7f43cc5c5f15241b5e6e5363256f19ceb990
Function Runtime Version: 3.0.14916.0


Functions:

        goodbye: [GET] http://localhost:7071/api/goodbye

        hello: [GET] http://localhost:7071/api/hello

For detailed output, run func with --verbose flag.
[2020-12-14T20:24:34.786Z] Worker process started and initialized.
내부에서 Azure Function Core Tools를 시작한 후 시작합니다.
cURL로 두드려 주세요.
$ curl -v 'http://localhost:7071/api/hello?name=world'
*   Trying 127.0.0.1:7071...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 7071 (#0)
> GET /api/hello?name=world HTTP/1.1
> Host: localhost:7071
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 14 Dec 2020 20:28:29 GMT
< Content-Type: text/plain; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
Hello world%
hello/functions.json에서 Azure Function의 함수 설정이 생성되었습니다.
{
  "disabled": false,
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "authLevel": "anonymous",
      "methods": [
        "GET"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ],
  "entryPoint": "sayHello",
  "scriptFile": "../src/handlers/hello.js"
}

프로그램 설계


자신의 환경에 여러 프로그램이 있기 때문에 사전에 이 단계 대로 서비스 프린시피를 만들지 않으면 오류가 발생한다.
내가 먼저 드라이런부터 해볼게.
$ sls deploy --dryrun
Serverless: Initializing provider configuration...
Serverless: Configuration warning: Unrecognized provider 'azure'
Serverless:  
Serverless: You're relying on provider plugin which doesn't provide a validation schema for its config.
Serverless: Please report the issue at its bug tracker linking: https://www.serverless.com/framework/docs/providers/aws/guide/plugins#extending-validation-schema
Serverless: You may turn off this message with "configValidationMode: off" setting
Serverless:  
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: hello event: httpTrigger
Serverless: Building binding for function: goodbye event: httpTrigger
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Logging into Azure
Serverless: Using subscription ID: 7a9f3ee7-623e-4aad-adec-6e8305f54de8
Serverless: -> Creating ARM template from type: consumption
Serverless: 
Resource Group Name: sls-wus2-dev-helloworld-rg
Function App Name: sls-wus2-dev-helloworld
Functions:
        hello
        goodbye
Azure Resources:
{
  "name": "sls-wus2-dev-helloworld",
  "resourceType": "Microsoft.Web/sites",
  "region": "westus2"
},
{
  "name": "sls-wus2-dev-52c01f-appinsights",
  "resourceType": "microsoft.insights/components",
  "region": "westus2"
},
{
  "name": "slswus2dev52c01f",
  "resourceType": "Microsoft.Storage/storageAccounts",
  "region": "westus2"
}

****************************************************************************************************************************
Serverless: Announcing an enhanced experience for running Express.js apps: https://github.com/serverless-components/express.
****************************************************************************************************************************
그럼 제가 실제 테스트를 해볼게요.
$ sls deploy
Serverless: Initializing provider configuration...
Serverless: Configuration warning: Unrecognized provider 'azure'
Serverless:  
Serverless: You're relying on provider plugin which doesn't provide a validation schema for its config.
Serverless: Please report the issue at its bug tracker linking: https://www.serverless.com/framework/docs/providers/aws/guide/plugins#extending-validation-schema
Serverless: You may turn off this message with "configValidationMode: off" setting
Serverless:  
Serverless: Removing .serverless directory
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Parsing Azure Functions Bindings.json...
Serverless: Building binding for function: hello event: httpTrigger
Serverless: Building binding for function: goodbye event: httpTrigger
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Logging into Azure
Serverless: Using subscription ID: 7a9f3ee7-623e-4aad-adec-6e8305f54de8
Serverless: Creating resource group: sls-wus2-dev-helloworld-rg
Serverless: Creating function app: sls-wus2-dev-helloworld
Serverless: -> Creating ARM template from type: consumption
Serverless: -> Merging environment configuration
Serverless: Listing deployments for resource group 'sls-wus2-dev-helloworld-rg':
Serverless: -> Deploying ARM template...
Serverless: ---> Resource Group: sls-wus2-dev-helloworld-rg
Serverless: ---> Deployment Name: slswus2devhelloworld-DEPLOYMENT-t1607978610276
Serverless: -> ARM deployment complete
Serverless: Deploying serverless functions...
Serverless: Deploying zip file to function app: sls-wus2-dev-helloworld
Serverless: -> Deploying service package @ /home/masa/work/serverless-helloworld/05/helloworld/.serverless/helloworld.zip
Serverless: Publishing to URI: https://sls-wus2-dev-helloworld.scm.azurewebsites.net/api/zipdeploy
Serverless: Uploading file at '/home/masa/work/serverless-helloworld/05/helloworld/.serverless/helloworld.zip' to container 'deployment-artifacts' with name 'slswus2devhelloworld-ARTIFACT-t1607978610276.zip'
Serverless: Finished uploading blob
Serverless: -> Function package uploaded successfully
Serverless: Deployed serverless functions:
Serverless: -> Function App not ready. Retry 0 of 30...
Serverless: -> Function App not ready. Retry 1 of 30...
Serverless: -> Function App not ready. Retry 2 of 30...
Serverless: -> Function App not ready. Retry 3 of 30...
Serverless: -> Function App not ready. Retry 4 of 30...
Serverless: -> Function App not ready. Retry 5 of 30...
Serverless: -> Function App not ready. Retry 6 of 30...
Serverless: -> goodbye: [GET] sls-wus2-dev-helloworld.azurewebsites.net/api/goodbye
Serverless: -> hello: [GET] sls-wus2-dev-helloworld.azurewebsites.net/api/hello

********************************************************************************************************************************************
Serverless: Announcing an enhanced experience for Serverless Full-Stack Applications: https://github.com/serverless-components/fullstack-app
********************************************************************************************************************************************
표시된 끝점을 cURL로 두드립니다.
$ curl -v 'https://sls-wus2-dev-helloworld.azurewebsites.net/api/hello?name=world'                                                                  <main 5:52>
*   Trying 40.64.128.228:443...
* TCP_NODELAY set
* Connected to sls-wus2-dev-helloworld.azurewebsites.net (40.64.128.228) port 443 (#0)

...(省略)...

> GET /api/hello?name=world HTTP/1.1
> Host: sls-wus2-dev-helloworld.azurewebsites.net
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Content-Type: text/plain; charset=utf-8
< Request-Context: appId=cid-v1:dfbf56f5-90c1-446c-a8b8-10cc10d770b4
< Date: Mon, 14 Dec 2020 20:52:43 GMT
< 
* Connection #0 to host sls-wus2-dev-helloworld.azurewebsites.net left intact
Hello world%
sls invoke도 명령을 통해 직접 호출할 수 있다.
$ sls invoke -f hello -d '{"name":"World"}'
Serverless: Initializing provider configuration...
Serverless: Configuration warning: Unrecognized provider 'azure'
Serverless:  
Serverless: You're relying on provider plugin which doesn't provide a validation schema for its config.
Serverless: Please report the issue at its bug tracker linking: https://www.serverless.com/framework/docs/providers/aws/guide/plugins#extending-validation-schema
Serverless: You may turn off this message with "configValidationMode: off" setting
Serverless:  
Serverless: Logging into Azure
Serverless: Using subscription ID: 7a9f3ee7-623e-4aad-adec-6e8305f54de8
Serverless: Invocation url: http://sls-wus2-dev-helloworld.azurewebsites.net/api/hello?name=World
Serverless: Invoking function hello with GET request
Serverless: "Hello World"
Azure에서 Hello 함수를 프로그래밍할 수 있습니다.

좋은 웹페이지 즐겨찾기