12
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Azure Functions App × Python で Azure CosmosDB にアクセスしてみる

Last updated at Posted at 2018-12-17

Serverless で何か処理を行いたいときに便利な Azure Function App。
Web API から Azure CosmosDB をアップデートするという操作を行いたく、新しく対応した Python で実装してみましたので、手順を紹介します。

苦労したところ

  • Azure Functions で Python を利用できるのは Linux サーバー、Function App の開発をするのは Windows ということで
    • Visual Studio Code + Azure Functions Extention を利用して開発を進めていたのですが、仮想 Web サーバー(venv) が自動起動せず、結局手動で起動して進めました
    • Azure へデプロイする際に ローカルの Docker (Linux Container) が必要でした

実行環境

手順

1. Azure Function Python App を Azure 上に作成
2. Azure Function Python App をローカルで作成

1. Azure Function App を Azure 上に作成

Azure Portal から Azure サブスクリプション が 紐づいたアカウントでサインインします。
[+新規作成] をクリック、Function App と検索して Function App を新規作成します。
Python を選択するには、Linux サーバーを選択する必要があります。
今回は PyCosmosFunc という名前で作成しています。
20181217_01.PNG

2. Azure Function App をローカルで作成

2-1. Function Python App の新規作成

Azure Function Core Tools (ターミナル) を使う方法と、Azure Function ツール (GUI) を使う方法、いずれかで Function の作成を行ってください。

2-1-a. Azure Function Core Tools を使う場合

ターミナルから作成を行います。
Visual Studio Code を開き、Open Folder をクリック、プロジェクトを配置する任意のフォルダーを指定して開きます。
20181217_02.PNG

Azure Function をローカルで作成、起動するには venv の環境が必要です。
ツールバーの [Terminal] > [New Terminal] でターミナルを開き、venv をインストールして起動します。

> python -m venv venv
> venv\scripts\activate

venv を起動した状態で、Azure Function App を作成します。

(venv)> func init

runtime は python を選択します。

Select a worker runtime: python

Azure Function のスターターテンプレートから App (Project) が作成されます。
20181217_03.PNG

Azure Function App に Function を作成します。

(venv)> func new

Template は HTTPTrigger, name は デフォルトのまま (HTTPTrigger) にします。

Select a template: HTTP trigger
Function name: [HttpTrigger]

Azure Function App 内に HttpRequest テンプレートから Function が作成されます。
20181217_04.PNG

2-1-b. Azure Function ツールを使う場合

Visual Studio Code に統合されたツールを利用します。
Visual Studio Code を開き、Azure Tools のタブを開きます。
Azure Function の Create New Project をクリックして Function App を作成します。
20181217_a02.PNG

Runtime は Python を選択します。
20181217_a03.PNG

今の Windows で開くには Open in current window を選択します。
20181217_a04.PNG

Azure Function をローカルで作成、起動するには venv の環境が必要です。
.env フォルダに venv がインストールされているので、Terminal を開いてコマンドプロンプトで起動します。

> .env\scripts\activate

再び Azure Tools のタブにある Azure Function の Create New Function をクリックして Function を作成します。
20181217_a05.PNG

作成した App のフォルダを選択します。
20181217_a06.PNG

Function の種類は HTTPTrigger を選択します。
20181217_a07.PNG

Function Name はデフォルト (HTTPTrigger) のままにします。
20181217_a08.PNG

Authorization Level は Functions を選択します。
20181217_a09.PNG

Azure Function App 内に HttpRequest テンプレートから Function が作成されます。
20181217_a10.PNG

2-2. Function Python App のテスト

Function App が起動すると、HttpTrigger > __init__.py が実行されます。
HTTP GET または POST を行うと、送信されたパラメータ(name)を取得して Hello {name}! と表示するという簡単なものです。

__init__.py
import logging
import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello {name}!")
    else:
        return func.HttpResponse(
             "Please pass a name on the query string or in the request body",
             status_code=400
        )

ターミナルから起動して動作を確認します。

(venv)> func start

以下のようなメッセージが表示されたら起動完了です。ブラウザーを起動して HttpTrigger の URLにアクセスします。

Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.

Http Functions:

        HttpTrigger: [GET,POST] http://localhost:7071/api/HttpTrigger

まず、なにもパラメータがない場合はメッセージが表示されます。
20181217_06.PNG

このようにパラメーターを追加すると名前が表示されるようになります。

http://localhost:7071/api/HttpTrigger?user=annie

20181217_07.PNG

ターミナルから Ctrl+C で一旦アプリを停止します。

2-3. Function App で CosmosDB にアクセスする

Azure Cosmos DB を操作する API を作成していきます。
パラメーターが取得できた場合、Azure Cosmos DB のデータベース、コレクション(コンテナー)を参照して、ドキュメント数を表示するようにします。
パラメーターは database, container とします。

Azure CosmosDB 用パッケージの追加

CosmosDB を操作するには、Python 用のモジュール(azure-cosmos)が公開されていますので、それを利用します。コマンドプロンプトから pip でインストールします。

(venv)> pip install azure-cosmos

このとき表示される azure-cosmos のバージョン(2018年12月現在、v3.0.2)を確認します。

(venv)> pip install azure-cosmos
Collecting azure-cosmos
 :
Installing collected packages: idna, certifi, chardet, urllib3, requests, azure-cosmos
Successfully installed azure-cosmos-3.0.2 certifi-2018.11.29 chardet-3.0.4 idna-2.8 requests-2.21.0 urllib3-1.24.1

この情報を requirements.txt に追加します。

requirements.txt
azure-cosmos==3.0.2

外部スクリプトの作成

HTTPTrigger と同じ階層に SharedScripts という名前でフォルダを追加、その中に Cosmos.py という名前でファイルを作成します。

Cosmos.py を記述します。ポイントは

  • import azure.cosmos.cosmos_client でモジュールをインポートしています
  • CosmosDBの接続情報は冒頭、config で設定しています。(※本来であれば、別途 config ファイル等に記載すべきですが、動作確認のため直接記載しています)
    • ENDPOINT および PRIMARYKEY にお持ちの Azure CosmosDB の設定を入力してください
  • CountDocuments で database および container を引数として、document の数を返します
cosmos.py
import azure.cosmos.cosmos_client as cosmos_client

def CountDocuments(database,container):
    config = {
        'ENDPOINT': 'YOUR_COSMOSDB_ENDPOINT',
        'PRIMARYKEY': 'YOUR_COSMOSDB_KEY',
        'DATABASE': database,
        'CONTAINER': container
    }

    # Initialize the Cosmos client
    client = cosmos_client.CosmosClient(url_connection=config['ENDPOINT'], auth={
                                        'masterKey': config['PRIMARYKEY']})

    # Connect to a database
    database_link = 'dbs/' + config['DATABASE']
    db = client.ReadDatabase(database_link)

    # Connect to a container
    container_definition = {
        'id': config['CONTAINER']
    }
    container_link = database_link + '/colls/{0}'.format(config['CONTAINER'])
    container = client.ReadContainer(container_link)

    # Query these items in SQL
    query = {'query': 'SELECT * FROM server s'}

    options = {}
    options['enableCrossPartitionQuery'] = True
    options['maxItemCount'] = 2

    result_iterable = client.QueryItems(container['_self'], query, options)
    count = 0
    for item in iter(result_iterable):
        count = count +1

    #return count
    msg = str(count) + ' document(s) found in DB'
    return msg

init.py の修整

database および container というパラメーターを取得して処理を行うように __init.py__ を修正します。ポイントは

  • 作成した SharedScripts > Cosmos.py から CountDocuments を import します
  • database および container のパラメーターが取得できた場合は CountDocuments を呼び出します
  • どちらかのパラメーターが取得できない場合は、パラメーターが必要な旨のメッセージを表示します
__init__.py
import logging
import azure.functions as func
from ..SharedScripts import cosmos

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    database = req.params.get('database')
    container = req.params.get('container')
    if not database:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            database = req_body.get('database')
    if not container:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            container = req_body.get('container')

    if database is not None and container is not None:
        msg = cosmos.CountDocuments(database,container)
        return func.HttpResponse(
            msg,
            status_code=200
        )
    else:
        return func.HttpResponse(
             "Please pass database and container name on the query string or in the request body",
             status_code=400
        )

再びテスト実行

ここで再度実行します。

(venv)> func start

HTTPTrigger の URL をブラウザーで開きます。

http://localhost:7071/api/HttpTrigger

パラメーターがないときは、パラメーターが必要な旨のメッセージが表示されます。
20181217_09.PNG

パラメーターとしてお持ちの Azure CosmosDB の Database 名と Container 名をセットします。

http://localhost:7071/api/HttpTrigger?database=YOUR_COSMOSDB&container=YOUR_CONTAINER

CosmosDB 内のドキュメント数が返されれば OK です。
20181217_10.PNG

3. ローカルで作成した Azure Function App を Azure にデプロイ

Linux 環境が必要となるため、Docker for Windows (Linux Container) を起動しておきます。

Visual Studio Code のターミナルから Azure CLI で Azure にサインインします。

> az login

ブラウザーが開くので、1. と同じアカウントでサインインします。
Login Success と表示されたら Visual Studio Code に戻ります。

複数サブスクリプションを持っている場合は、使用するサブスクリプション(YOUR_SUBSCRIPTION)をセットします。

> az account set --subscription YOUR_SUBSCRIPTION

Visual Studio Code のターミナルから Azure Function App (今回は PyCosmosFunc) へ Azure Function Core Tools を使ってデプロイします。
ポイントは、--nozip オプション および --build-native-deps オプションで、(Docker を利用して)ビルド後にデプロイすることです。

> func azure functionapp publish PyCosmosFunc --nozip --build-native-deps

以下のようなメッセージが表示されたらデプロイ完了です。

Upload completed successfully.
Functions in PyCosmosFunc:
    HttpTrigger - [httpTrigger]
        Invoke url: http://YOUR_FUNCTION_NAME.azurewebsites.net/api/httptrigger?code=YOUR_FUNCTION_ACCESSCODE

表示されている URL にブラウザーからアクセスします。code というパラメーターでアクセスコードが付与されています。

http://YOUR_FUNCTION_NAME.azurewebsites.net/api/httptrigger?code=YOUR_FUNCTION_ACCESSCODE

database と container のパラメーターを入力していないので、パラメーターが必要な旨のメッセージが表示されればOKです。
20181217_11.PNG

URL の後ろに &database=YOUR_DATABASE&container=YOUR_CONTAINER の形式でパラメーターを入力して再度アクセスします。

http://YOUR_FUNCTION_NAME.azurewebsites.net/api/httptrigger?code=YOUR_FUNCTION_ACCESSCODE&database=YOUR_DATABASE&container=YOUR_CONTAINER

Document の数が表示されれば完了です。
20181217_12.PNG

12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?