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

Ansible の lineinfile で with_items を使うときの 駄目な書き方 と 正しい書き方

Ansible 開発

こんにちは、最近 Ansible を使い始めたので猛烈に勉強しています。

Ansible は英語の情報だらけで日本語の情報がまだまだ少ないです。 その足しになれば良いと思います。

※ 記事公開から時間が経過している場合、この内容も古い可能性がありますのでご注意下さい。


さて、本題です。

先日、 Ansible のバージョンを 1.6.6 から 1.6.10 に上げたところ sshd の設定を行うところでエラーが発生しましたので、それを解決する方法を紹介します。

修正前は以下のように sshd の設定ファイルを書き換える処理を書いていました。

ググるとよく出てくる lineinfilewith_items を使った書き方ですが、いまや正常に動作しないので駄目な書き方とさせていただきます。

駄目な書き方

- name: configure sshd_config
  lineinfile: dest=/etc/ssh/sshd_config backup=yes {{item}}
  with_items:
    # パスワード認証禁止
    - regexp='^PasswordAuthentication' line='PasswordAuthentication no' insertafter='#PasswordAuthentication'
    # Root ログイン禁止
    - regexp='^PermitRootLogin' line='PermitRootLogin no' insertafter='#PermitRootLogin'
    # ポート番号変更
    - regexp='^Port' line='Port {{ssh_port}}' insertafter='#Port'


エラー

これは 1.6.6 以下では動作するけど、1.6.7 以降では動作しません。

1.6.7 以降では以下の様なエラーが発生します(長いので改行しています)。

A variable inserted a new parameter into the module args.
Be sure to quote variables if they contain equal signs (for example: "{{var}}").


何怒ってるの?

    - regexp='^Port' line='Port {{ssh_port}}' insertafter='#Port'

の部分の {{ssh_port}}"{{ssh_port}}" で囲め! って言われてます ({{item}} も)。

これは Security fixes の変更によるものだと思われます。

このエラーを回避するためには 1.6.7 Error, A variable inserted a new parameter into the module args #8260 の issue でも紹介されているように以下の様な書き方をします。

※ 単純に変数をダブルコーテーションで囲むだけでは別のエラーが発生します。

正しい書き方

{{item}} に行の一部を渡すのではなく、それぞれの引数をハッシュとして渡す方針で修正します。

- name: configure sshd_config
  lineinfile: dest=/etc/ssh/sshd_config
              backup=yes
              regexp="{{item.regexp}}"
              insertafter="{{item.insertafter}}"
              line="{{item.line}}"
  with_items:
    # パスワード認証禁止
    - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no', insertafter: '#PasswordAuthentication' }
    # Root ログイン禁止
    - { regexp: '^PermitRootLogin', line: 'PermitRootLogin no', insertafter: '#PermitRootLogin' }
    # ポート番号変更
    - { regexp: '^Port', line: 'Port "{{ ssh_port }}"', insertafter: '#Port' }

これでうまく動作しました。

同じ現象で困っている人はお試しあれ!

まとめ

以上でございます。