AWS SDK for Python (Boto3) で Glue ワークフローを実行する際にパラメータを指定してみる

2022.06.28

いわさです。

AWS Glue ではワークフローとジョブを使ってETLを構築することが出来ますが、ワークフローには実行パラメータが存在します。
今回、オンデマンドトリガーのワークフローをLambda関数からBoto3を使って実行した際に、実行パラメータを渡せないことに気がついたので、対処方法をご紹介します。

やりたかったこと

適当なジョブを構成したワークフローを外部から手動実行する際にパラメータを渡そうと考えていました。
パラメータを動的に柔軟に行うようなケースでLambdaからの実行を行いたいシーンを想定したものになります。

ジョブは適当に、Python Shellで以下のようにSNSトピックへ通知を送信するものを用意します。

import sys
import boto3
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ['key1'])

sns = boto3.client('sns')
res = sns.publish(
    TopicArn = 'arn:aws:sns:ap-northeast-1:123456789012:general-topic-iwasaclassmethod',
    Message = args['key1'],
    Subject = args['key1']
)

そして、オンデマンドトリガーと接続し、AWS CLIのstart-workflow-runでパラメータを付与した上で実行します。

$ aws glue start-workflow-run --name hoge0621workflow --run-properties key1=hogeiwasa
{
    "RunId": "wr_f0550e3ab8afe425d5d0896e744b242d90b749d22e268b32ab0ef5d0d3f80be8"
}

実行されて、この場合だとkey1に指定したhogeiwasaがメッセージとしてメール送信されています。

LambdaからBoto3を使って実行

このAWS CLIで行っている、パラメータを追加してワークフローを実行する部分ですが、Boto3ではRunPropertiesが用意されています。

しかし、Lambda関数で Python 3.9 の関数を作成し、リファレンスに従って実装するだけだとエラーが発生します。

import json
import boto3

def lambda_handler(event, context):
    glue = boto3.client('glue')
    newRun = glue.start_workflow_run(
        Name = 'hoge0621workflow',
        RunProperties = { 'key1': 'value1' })
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

{
  "errorMessage": "Parameter validation failed:\nUnknown parameter in input: \"RunProperties\", must be one of: Name",
  "errorType": "ParamValidationError",
  "requestId": "bd0ff287-17ad-4e23-9701-1362f34d70c5",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 6, in lambda_handler\n    newRun = glue.start_workflow_run(Name = 'hoge0621workflow', RunProperties = { 'key1': 'value1' })\n",
    "  File \"/var/runtime/botocore/client.py\", line 391, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n",
    "  File \"/var/runtime/botocore/client.py\", line 691, in _make_api_call\n    request_dict = self._convert_to_request_dict(\n",
    "  File \"/var/runtime/botocore/client.py\", line 739, in _convert_to_request_dict\n    request_dict = self._serializer.serialize_to_request(\n",
    "  File \"/var/runtime/botocore/validate.py\", line 360, in serialize_to_request\n    raise ParamValidationError(report=report.generate_report())\n"
  ]
}

RunPropertiesが使えないようです。

対処方法

LambdaでBoto3を使う際にありがちなのですが、LambdaのPythonランタイムで用意されているデフォルトのBoto3バージョンが最新ではなく、期待どおりの動作をしないことがあります。
今回もそのケースで、最新バージョン(本日時点で1.24.xx)であれば実行することが出来ます。

そこで、以下のようにLambdaレイヤーを使って最新版のBoto3をインストールしたレイヤーを用意し、関数で利用してみます。

今度は、成功しましたね。

SNS通知を確認することが出来ました。
Lambdaで指定したパラメータがGlueワークフローに渡り、ジョブまで渡っていることが確認出来ました。

さいごに

本日は、Glueワークフローの実行パラメータをLambdaのBoto3から設定する方法を紹介しました。
蓋をあけてみるとBoto3のバージョンが低かったというだけではあるのですが、そこに至るまで私はだいぶ遠回りしました。

Lambda Boto3 で期待した挙動をしないときは、ローカルに最新Boto3環境を作成し確認するということを徹底しようと心に誓ったのでした。