13
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

細かすぎて伝わらないAWSCLI芸

LL言語のAWS SDKなど甘えだ!(挨拶

AWSオペレータの職を初めてから1年半ほど、何かとAWSCLIで作業(主に現在の設定値の洗い出し等)することが多く、ときにはパッと見で難解なワンライナーが出来上がってしまうため、引き継ぎ&個人のメモがてら記事にした次第です。

お決まり文句ですが、 本記事の情報を利用した結果、生じた金銭やセキュリティ被害等の損害について、一切責任を負いません。 きちんと検証した上でご利用ください。
また各コマンドのオプション等は各自お調べください。

あと、以下の環境にて動作確認をしております。方言的なところは逐次変更してください。

  • AWSCLI(1.11.37)
  • jq(1.5)
  • zsh(5.0.8、ちょっと古いですね)

その1:多段リクエスト

1回目のAWSCLIの結果を2回目に使いたい・・・という場合はよくあります。
これを実現するには xargsコマンドかfor文を使うとできます。
xargsの場合は、必然的に jq コマンドを使用することになるかと思います。

例: RDSのパラメータグループのKeyとValueを取得する(describe-db-parameter-groups -> describe-db-parameters)

  • xargs & jq
$ aws rds describe-db-parameter-groups \
  | jq '.DBParameterGroups[].DBParameterGroupName' -r \
  | xargs -I% aws rds describe-db-parameters --db-parameter-group-name % \
  | jq '.Parameters[]|{Name: .ParameterName, Value: .ParameterValue}'
  • for文(トップレベルが配列になります)
$ for db in $(aws rds describe-db-parameter-groups --query 'DBParameterGroups[*].DBParameterGroupName' --output text);
do
  aws rds describe-db-parameters --db-parameter-group-name ${db} \
    --query 'Parameters[*].{Name:ParameterName,Value:ParameterValue}'
done

その2:その1をしつつ特定文字列を含むものに絞り込みしたい

jqを使う場合はselect、awscliの場合はqueryオプション内でfilterします。

例: character という文字列が入ったパラメータ名(例えばcharacter_set_client とか)のみを出力したい

  • xargs & jq
$ aws rds describe-db-parameter-groups \
  | jq '.DBParameterGroups[].DBParameterGroupName' -r \
  | xargs -I% aws rds describe-db-parameters --db-parameter-group-name % \
  | jq '.Parameters[]|select(.ParameterName|contains("character"))|{Name: .ParameterName, Value: .ParameterValue}'
  • awscli
$ for db in $(aws rds describe-db-parameter-groups --query 'DBParameterGroups[*].DBParameterGroupName' --output text);
do
  aws rds describe-db-parameters --db-parameter-group-name ${db} \
    --query 'Parameters[?contains(ParameterName, `character`)].{Name:ParameterName,Value:ParameterValue}'
done

その3:その2をしつつ特定文字列を含むものを除外したい

jqの場合、論理演算子を使う方法とパイプを使ってフィルタする方法があります。状況に応じて変えましょう。
awscliは論理演算子を駆使します。
もし truefalse を使う場合はバッククォートで囲む必要があるので注意しましょう。

例: handshake という文字列が入ったものを除外する

  • xargs & jq (論理演算子)
$ aws rds describe-db-parameter-groups \
  | jq '.DBParameterGroups[].DBParameterGroupName' -r \
  | xargs -I% aws rds describe-db-parameters --db-parameter-group-name % \
  | jq '.Parameters[]|select(.ParameterName|contains("character") and (contains("handshake")|not))|{Name: .ParameterName, Value: .ParameterValue}'
  • xargs & jq (パイプ)
$ aws rds describe-db-parameter-groups \
  | jq '.DBParameterGroups[].DBParameterGroupName' -r \
  | xargs -I% aws rds describe-db-parameters --db-parameter-group-name % \
  | jq '.Parameters[]|select(.ParameterName|contains("character"))|select(.ParameterName|contains("handshake")|not)|{Name: .ParameterName, Value: .ParameterValue}'
  • awscli
$ for db in $(aws rds describe-db-parameter-groups --query 'DBParameterGroups[*].DBParameterGroupName' --output text);
do
  aws rds describe-db-parameters --db-parameter-group-name ${db} \
    --query 'Parameters[?contains(ParameterName, `character`) && !contains(ParameterName, `handshake`)].{Name:ParameterName,Value:ParameterValue}'
done
  • awscli (false使用)
$ for db in $(aws rds describe-db-parameter-groups --query 'DBParameterGroups[*].DBParameterGroupName' --output text);
do
  aws rds describe-db-parameters --db-parameter-group-name ${db} \
    --query 'Parameters[?contains(ParameterName, `character`) && contains(ParameterName, `handshake`) == `false`].{Name:ParameterName,Value:ParameterValue}'
done

その4:その3をしつつトップレベルに識別子キーを入れたい

その1〜3の例だと、どのPGの値かわからない・・・ので、トップレベルにPG名を入れます。
ここからはシェルのパイプラインでPG名を渡せないので、xargsを使わずに awscli & --query オプションでがんばります。

また、シェル変数展開する必要があるため、awscliのqueryに渡していた文字列をシングルクォート囲いからダブルクォート囲いにして、文字列内のダブルクォート・バッククォートをエスケープします。

例:トップレベルのキーにdb-parameter-group-nameを入れる。

$ for db in $(aws rds describe-db-parameter-groups --query 'DBParameterGroups[*].DBParameterGroupName' --output text);
do
  aws rds describe-db-parameters --db-parameter-group-name ${db} \
    --query "{\"${db}\":Parameters[?contains(ParameterName, \`character\`) && !contains(ParameterName, \`handshake\`)].{Name:ParameterName,Value:ParameterValue}}"
done

出力

{
    "aibou-db-parameters": [
        {
            "Name": "character_set_client",
            "Value": "utf8mb4"
        },
        {
            "Name": "character_set_connection",
            "Value": "utf8mb4"
        },
        {
            "Name": "character_set_database",
            "Value": "utf8mb4"
        },
        {
            "Name": "character_set_filesystem",
            "Value": "utf8mb4"
        },
        {
            "Name": "character_set_results",
            "Value": "utf8mb4"
        },
        {
            "Name": "character_set_server",
            "Value": "utf8mb4"
        }
    ],
    # 続く
}

key名を変数展開したい(未解決)

{
  "character_set_client" : "utf8mb4",
  "character_set_connection" : "utf8mb4"
}

の様な出力がほしかったものの、awscliでもjqでも方法わからず(コメントや記事リクエスト等で受付させていただきます。)

その他(awscli alias)

awscliでaliasを作ることができます。 詳しくはこちら: http://dev.classmethod.jp/cloud/aws/aws-cli-alias/

functionを定義できるのが非常に魅力的なのですが、現状引数を(与えられない/取れない)仕様になっているようです。
どうしても引数を使いたい場合は、 下記を試されると良いかなと思います。
(僕はこの方法を見てドン引きしました。)
https://github.com/awslabs/awscli-aliases/issues/19#issuecomment-280524125

終わりに

他に書き方生まれたら & 気が向いたら逐次追加していきます。
コメント等でご提案・ご指摘も受けさせていただきます。

参考記事: http://dev.classmethod.jp/cloud/awscli-enhanced-query-opt-snipets/

(クラメソさんブログのリンクが多めですが、決して回し者ではありません。僕のポッケには1円も入らないです)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
13
Help us understand the problem. What are the problem?