読者です 読者をやめる 読者になる 読者になる

ぺーぺーSEのブログ

備忘録・メモ用サイト。

AWSコマンドラインインターフェース(AWS CLI)でAPI Gateway+AWS Lambdaを構築してみる(その3)

AWS AWS CLI API Gateway AWS Lambda jq

下記の記事で紹介したAWS CLIでのAPI GatewayAWS Lambdaの構築をJenkins等で実行できるようにbash化する。

tanakakns.hatenablog.com

jqの導入

jqJSONの内容をsedawkのようにフィルタ・加工するためのコマンド。
これを使ってAWS CLIのレスポンスのJSONから欲しい値をとる。
公式はここ

インストール

yumでインストールできる。

yum -y install jq

使い方

JSONの例は以下を使う。

■person.json

{"name":"Taro","age":20,"brother":{"name":"Jiro","age":18}}

■people.json

{"people":[{"name":"Taro","age":20},{"name":"Jiro","age":18}]}

全部は紹介しない。

整形

jq .

$ cat person.json | jq .
{
  "name": "Taro",
  "age": 20
}

値の取得

jq .[属性名]

$ cat person.json | jq .name
"Taro"
$ cat person.json | jq .brother.name
"Jiro"

値の取得(配列)

[]」をつけると配列の意味になる。

$ cat people.json | jq .people[].name
"Taro"
"Jiro"

ダブルクォートが邪魔

「-r」をつける。

$ cat people.json | jq -r .people[].name
Taro
Jiro

フィルタ(というかパイプ)

「jq "なにか | なにか"」の形。
jqの引数をダブルクォートでくくって、中をパイプで区切る。

$ cat people.json | jq -r ".people[] | .name"
Taro
Jiro

people配列だけを取得して、その配列からnameを抽出している。

結果からJSON作成

パイプの後ろをJSON形式にするだけ。

$ cat people.json | jq ".people[] | { personName: .name }"
{
  "personName": "Taro"
}
{
  "personName": "Jiro"
}

作成したbash

断っておくが、筆者は普段bashを書かない。
ロジックやエラーハンドリングはアホかもしれないが、とりあえずド正常なら動く。
てかほぼ前記事の手順を貼り付けただけw

#!/bin/bash

export account_id="123456789012" # AWSアカウント
export lambda_function_name="cliLambdaSample" # Lambda関数の名前
export role_exec_lambda="role_exec_lambda" # Lambdaを実行する権限を持つロール
export lambda_handler="org.sample.handler.PersonHandler::getPerson" # ハンドラ
export jar_path="LambdaSample-1.0-SNAPSHOT.jar" # Lambdaに登録するプログラム

export rest_api_name="cliApiSample" # API Gatewayに作成するAPIの名前
# export rest_api_id # ロジックの途中で使う変数
# export rest_api_root_path_id # ロジックの途中で使う変数
export rest_api_path_name="cliPathSample" # APIに作成するパス
export rest_api_method="GET" # API Gatewayに登録するHTTPメソッド

export permission_statement_id="12345678901234567890123456789012" # パーミッションのステートメントID

export deploy_stage_name="test" # API Gatewayをデプロイするステージ
# export deploy_id # ロジックの途中で使う変数

function checkError() {
  result=$1
  if [ $result -ne 0 ] ; then
    echo "Error occurred ! Exit code is ${result}."
    exit $result
  fi
}

aws lambda create-function \
 --function-name ${lambda_function_name} \
 --runtime       java8 \
 --role          arn:aws:iam::${account_id}:role/${role_exec_lambda} \
 --handler       ${lambda_handler} \
 --zip-file      fileb://${jar_path} \
1>/dev/null 2>/dev/null

checkError $?

export rest_api_id=(` \
  aws apigateway create-rest-api \
   --name ${rest_api_name} \
  | jq -r .id \
`)

checkError $?

export rest_api_root_path_id=(` \
  aws apigateway get-resources \
   --rest-api-id ${rest_api_id} \
  | jq -r .items[].id \
`)

checkError $?

export rest_api_path_id=(` \
  aws apigateway create-resource \
   --rest-api-id ${rest_api_id} \
   --parent-id   ${rest_api_root_path_id} \
   --path-part   ${rest_api_path_name} \
  | jq -r .id
`)

checkError $?

aws apigateway put-method \
 --rest-api-id ${rest_api_id} \
 --resource-id ${rest_api_path_id} \
 --http-method ${rest_api_method} \
 --authorization-type NONE \
1>/dev/null 2>/dev/null

checkError $?

aws apigateway put-integration \
 --rest-api-id ${rest_api_id} \
 --resource-id ${rest_api_path_id} \
 --http-method ${rest_api_method} \
 --type AWS \
 --integration-http-method POST \
 --uri arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:${account_id}:function:${lambda_function_name}/invocations \
1>/dev/null 2>/dev/null

checkError $?

aws apigateway put-integration-response \
 --rest-api-id ${rest_api_id} \
 --resource-id ${rest_api_path_id} \
 --http-method ${rest_api_method} \
 --status-code 200 \
 --response-templates '{"application/json":""}' \
1>/dev/null 2>/dev/null

checkError $?

aws lambda add-permission \
 --function-name ${lambda_function_name} \
 --statement-id ${permission_statement_id} \
 --action lambda:InvokeFunction \
 --principal apigateway.amazonaws.com \
 --source-arn arn:aws:execute-api:ap-northeast-1:${account_id}:${rest_api_id}/${deploy_stage_name}/${rest_api_method}/${rest_api_path_name} \
1>/dev/null 2>/dev/null

checkError $?

aws apigateway put-method-response \
 --rest-api-id ${rest_api_id} \
 --resource-id ${rest_api_path_id} \
 --http-method ${rest_api_method} \
 --status-code 200 \
 --response-models '{"application/json":"Empty"}' \
1>/dev/null 2>/dev/null

checkError $?

aws apigateway test-invoke-method \
 --rest-api-id ${rest_api_id} \
 --resource-id ${rest_api_path_id} \
 --http-method ${rest_api_method} \
 --path-with-query-string "" \
1>/dev/null 2>/dev/null

checkError $?

export deploy_id=(` \
  aws apigateway create-deployment \
   --rest-api-id ${rest_api_id} \
   --stage-name  ${deploy_stage_name} \
   --stage-description "" \
   --description "" \
  | jq -r .id \
`)

checkError $?

echo "Process succeeded ! Following is URI."
echo "https://${rest_api_id}.execute-api.ap-northeast-1.amazonaws.com/${deploy_stage_name}/${rest_api_path_name}"

AWS Lambdaのコードや設定を更新するだけのシェルは以下。

#!/bin/bash

export account_id="123456789012"
export lambda_function_name="cliLambdaSample"
export role_exec_lambda="role_exec_lambda"
export lambda_handler="org.sample.handler.PersonHandler::getPerson"
export jar_path="LambdaSample-1.0-SNAPSHOT.jar"

function checkError() {
  result=$1
  if [ $result -ne 0 ] ; then
    echo "Error occurred ! Exit code is ${result}."
    exit $result
  fi
}

aws lambda update-function-code \
 --function-name ${lambda_function_name} \
 --zip-file      fileb://${jar_path} \
1>/dev/null 2>/dev/null

checkError $?

aws lambda update-function-configuration \
 --function-name ${lambda_function_name} \
 --role          arn:aws:iam::${account_id}:role/${role_exec_lambda} \
 --handler       ${lambda_handler} \
1>/dev/null 2>/dev/null

checkError $?

echo "Process succeeded !"

API GatewayAPIAWS Lambdaの関数を削除するだけのシェルは以下。

#!/bin/bash
export rest_api_name="cliApiSample" # 削除するAPI GatewayのAPIの名前
export lambda_function_name="cliLambdaSample" # 削除するLambda関数の名前

export rest_api_id=$( \
  aws apigateway get-rest-apis \
    --output json \
    | jq -r .items[] \
    | jq -r "select(.name == \"`echo ${rest_api_name}`\")" \
    | jq -r '.id'  \
)

aws apigateway delete-rest-api --rest-api-id ${rest_api_id}

aws lambda delete-function --function-name ${lambda_function_name}