続・Playbookで指定できる文字について の話
これは Ansible Advent Calendar 2019 の11日目の記事となります。
いつの間にかその2、その3もできてますね。
Ansible 2 Advent Calendar 2019 - Qiita
Ansible 3 Advent Calendar 2019 - Qiita
はじめに
今年の7月にAnsibleのコミュニティイベントでLT登壇の機会がありました。
内容としては
・①network_cliプラグインの内部の動き
・②Playbookで指定できる文字についての話
と5分で2つの内容を取り扱ったのですが、やはり時間的に無理がありまして、どちらかの内容だけに特化すればよかったと後日反省しました。
network_cliプラグインについては自分としてはとっても好きな部分なので、この先またなんらかの形でアウトプットができればとも思うのですが、②についてはLTの内容があまりにも不完全燃焼だったので、この場を借りて本来もう少し親切に書きたかった部分についてまとめておこうと思います。
結論はLT内容と変わりません
事前準備の情報
モジュールオプションのlist型
について
今回「Playbookで指定できる文字」で触れる部分ですが、もっと具体的にいうと「list型」で指定できる文字種となります。
これは例えばネットワーク機器で状態取得系のコマンドを指定する ios_command
モジュールのcommandsオプションであったり、telnet
モジュールのcommandオプションなどが使っている型となります。
ios_command
では、
「List of commands to send to the remote ios device over~」
と説明もされていますね。
また、
ソース上ではtype='list'
と指定している部分のオプションとなります。
argument_spec = dict( commands=dict(type='list', required=True),
少し補足ですが、各モジュールが提供するオプションにはそれぞれ型があり、型によって指定できるパラメータが定義されます。
この部分は、int型
、choices型(選択式)
、bool型
など色々とありますが、今回取り扱うlist型
は複数のコマンドを指定する場合に使われる型なので、比較的馴染みがあるかと思います。
ちょっと癖のある、bool型
などがYAMLフォーマット(Playbook)でどう扱われるか、についてはてくなべさんの記事でも取り上げられています。
tekunabe.hatenablog.jp ※上記エントリまとめ部分のYAMLフォーマットに対して指定した値がどう判断されるか
list型
をPlaybook内で指定する方法
話を戻して
今回取り扱うlist型
をPlaybookに記載する方法についてですが、恐らく以下の3パターンかと思っています。
①そのまま記載
- name: playbook pattern 1 xxx_command: commands: - show version
②シングルコーテーション囲み
- name: playbook pattern 2 xxx_command: commands: - 'show version'
③ダブルコーテーション囲み
- name: playbook pattern 3 xxx_command: commands: - "show version"
本記事について
伝えたい内容
この3パターンについて、
・指定可能な文字種が異なり
・送信可能な場合においても微妙にエスケープ方法が異なります
というのが本記事で扱う内容となります。
普段あまり困らないかもしれませんが、複雑な表現(例えば正規表現など)をPlaybookで記載する時などにお役に立てば幸いかなと。
注意
Playbookで指定できる文字について、はansibleコマンド
やansible-playbookコマンド
が実行できるまでの内容となります。
※--syntax-check
を通すまでの部分
Playbookが正常に実行された後は、ターゲット(のシェル)がその文字を解釈できるのかという別の要素も絡んでくる為、本記事ではあくまで「Playbookで指定できる文字」についての内容となります。
検証
検証環境
Ansible:2.9.0 Python :3.7.4 Module :ios_command
Playbook毎の使用文字種
それぞれの指定方法で、以下の文字列を指定して送信可能かどうかを確認しました
可視化文字列全てです。
!#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~
※大文字AとBの間に半角スペース含んでいます。
これをPlaybook化します。
①そのまま記載
ios_command: commands: - !#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~
と、明らかにシンタックスハイライトの時点で通らなそうですよね
--syntax-check
しても当然エラーとなります。
ERROR! Syntax Error while loading YAML. expected URI, but found '#' The error appears to be in '/xxx/xxx/xxx/ios_command.yml': line 19, column 12, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: commands: - !#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~ ^ here
なんか#
で怒られてますね。
前から順番に#
を削っても"
が怒られ、"
を削っても&
が怒られ、とこのパターンでは全ての文字種を送付するのは難しそうです。
②シングルコーテーション囲み
ios_command: commands: - '!#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~'
これも、そのまま指定して実行するとエラーとなります。
The offending line appears to be: commands: - '!#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~' ^ here
ですが、
シングルコーテーション'
はシングルコーテーション'
でエスケープできるので、以下のように書くとシンタックスエラーを回避できます。
※分かりにくいかもしれませんが、7つ目に指定しているシングルコーテーションを2回書いています。
※ブログ上のシンタックスハイライトもエスケープ前と比較してそれらしくなっている気がします。
ios_command: commands: - '!#"$%&''()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~'
③ダブルコーテーション囲み
ios_command: commands: - "!#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~"
これもそのまま実行するエラーとなります。「②シングルコーテーション囲み」よりもエラーが激しく、きちんとエスケープしなさいと例まで出ています。
commands: - "!#"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~" ^ here We could be wrong, but this one looks like it might be an issue with unbalanced quotes. If starting a value with a quote, make sure the line ends with the same set of quotes. For instance this arbitrary example: foo: "bad" "wolf" Could be written as: foo: '"bad" "wolf"'
ダブルコーテーションは、バックスラッシュ\
でダブルコーテーション"
とバックスラッシュ\
をエスケープできるので、以下のように書くとシンタックスエラーを回避できます。
ios_command: commands: - "!#\"$%&'()*+,-./0123456789:;<=>?@A BCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghIjklmnopqrstuvwxyz{|}~"
まとめ
Playbookのlist型で指定できる文字種は以下の点に注意すれば可視化文字全部指定できます。
指定方法 | ポイント |
---|---|
①そのまま指定 | 色々と送れない文字あり |
②シングルコーテーション囲み | シングルコーテーション' をシングルコーテーション ' でエスケープ |
③ダブルコーテーション囲み | ダブルコーテーション" とバックスラッシュ\ をバックスラッシュ \ でエスケープ |
シンタックスエラーではまってしまった時、私は、
「とりあえずシングルコーテーションで囲って、シングルコーテーションはシングルコーテーションでエスケープ」
する事で、多少複雑な指定をしてもPlaybook実行時やシンタックスチェックでハマらなくなりました。
という事で需要があるか分かりませんが、以上となります。