AWSのStep FunctionsからGlueジョブにパラメーターをJSONataで引き渡す方法
JSONPathを使いたくない
最近、タイトルのような作業を行う必要があり、AWSのほぼ初心者の私はネットでやり方を探していた。言うまでもなく、AWSのドキュメンテーションを先にチェックしたのだが、私の理解力には問題があるせいか、はっきりといった答えが見つからなかった。正確に書くと、「JSONata」でのはっきりといったやり方だ。
調査
AWSでJSONataを検索したら、このページがほとんどの場合が出てくる。JSONPathと違って、JSONataでは「Parameters」、「ResultPath」、「.$」などが使えないのはよく分かっていたし、「Parameters」の代わりに「Arguments」を使うことも理解できていた。それに、GlueジョブをStep Functionから起動させるAWSのドキュメンテーションには以下の例が書かれている:
"Glue StartJobRun": {
"Type": "Task",
"Resource": "arn:aws:states:::glue:startJobRun.sync",
"Arguments": {
"JobName": "GlueJob-JTrRO5l98qMG"
},
"Next": "ValidateOutput"
},
分かりやすい。Arguments
の中にJobName
というキーを設定し、値として実行したいジョブの名前を書く。ただ、そのジョブにパラメーターを渡したい場合はどうすればいいか書いていない。
実行したいGlueジョブに幾つかのパラメーターを渡さないといけないが、例として --target_date
を使う。GlueのスクリプトはPythonで書いてあるので、以下のコードでパラメーターを取得できる。
from awsglue.utils import getResolvedOptions
getResolvedOptions(sys.argv, ["target_date"])
AWS Consoleだと、Job Details -> Advanced Properties -> Job Parameters
でパラメーターの設定ができ、デフォルト値も設定可能。その設定をStep Functionsからやりたい。
Arguments
があるから、そのまま追加したらいいのでは?と思って、試してみた。
"My Job State": {
"Type": "Task",
"Resource": "arn:aws:states:::glue:startJobRun.sync",
"Arguments": {
"JobName": "MyGlueJobName",
"--target_date": "{% $target_date %}"
},
"Next": "Some other state"
}
エラーが表示された
[The field "--target_date" is not supported by Step Functions]
試行錯誤
頭にあるハイフンが問題かなと思い、消してみた
"My Job State": {
"Type": "Task",
"Resource": "arn:aws:states:::glue:startJobRun.sync",
"Arguments": {
"JobName": "MyGlueJobName",
"target_date": "{% $target_date %}"
},
"Next": "Some other state"
}
結果:
[The field "target_date" is not supported by Step Functions]
APIのチェックをした。確かに StartJobRun
にはArguments
があり、JobName
は必須。JobName
はArguments
の中にないといけないので、それは合っていることが分かった。
Arguments
に注目した:
Arguments – A map array of key-value pairs.
Each key is a UTF-8 string.
Each value is a UTF-8 string.
The job arguments associated with this run. For this job run, they replace the default arguments set in the job definition itself.
You can specify arguments here that your own job-execution script consumes, as well as arguments that AWS Glue itself consumes.
それに、Calling AWS Glue APIs in Pythonを参考にすることも書いてあり、Pythonで実行したいわけではないが、ヒントもらえると思ってチュックした。
from datetime import datetime, timedelta
client = boto3.client('glue')
def lambda_handler(event, context):
last_hour_date_time = datetime.now() - timedelta(hours = 1)
day_partition_value = last_hour_date_time.strftime("%Y-%m-%d")
hour_partition_value = last_hour_date_time.strftime("%-H")
response = client.start_job_run(
JobName = 'my_test_Job',
Arguments = {
'--day_partition_key': 'partition_0',
'--hour_partition_key': 'partition_1',
'--day_partition_value': day_partition_value,
'--hour_partition_value': hour_partition_value } )
ここで、start_job_run
の書き方はJobName
はArguments
の外にあり、Arguments
の中にジョブに渡したいパラメーターが設定されている。そのようにしようとしたら、State Machineを保存する段階で「JobNameはArgumentsには必須」のようなエラーが出て、実行すらできない。
LLMで調査
さて、LLMに効くかと思い、Gemini 2.5 Pro先生のところに行った。
LLMを使う前提
LLMにそもそも頼らない。使うときは間違ったことを言うのを前提として使う。
GeminiはどうしてもJSONpathでのやり方しか教えてくれない。JSONataに変更してと命令しても同じような間違ったコードを与えてくれる。簡潔にいうと、Parameters
を追加して、中に Arguments
を使ってパラメーターを渡すことが可能と主張する。
ChatGPTも同じようなことを答える。
余談
この2つのLLMの中で、一番正解に近かったのはGeminiだった。ChatGPTはエラーが多かった。
YouTubeでも探したが、この時点ではかなり疲れていたせいか、ダメ元で試したい方法が思い浮かんだ。
解決
分かる人にとってはとても簡単な問題であることは間違いないが、冒頭で述べたようにAWSの知識があるものの実際のフルソリューションを提供する経験が浅い私には明確ではなかった。
Arguments
の中にもう一つのArguments
を追加して、その中にパラメーターの設定をする
"My Job State": {
"Type": "Task",
"Resource": "arn:aws:states:::glue:startJobRun.sync",
"Arguments": {
"JobName": "MyGlueJobName",
"Arguments": {
"--target_date": "{% $target_date %}"
}
},
"Next": "Some other state"
}
これを解決するのにかなりの時間がかかった。
英語で(主に)Googleで解決方法を探す「能力」は俗に「Google-Fu」と言う(Kung-Fuから転じて)。私のGoogle-Fuは今回足りなかったか、そもそもこの問題が簡単すぎて明確な解決方法を書くまでもないか分からない。
Discussion