notebook

都内でWEB系エンジニアやってます。

ansible-lintのバージョンをv6に上げたときの作業ログ

dotfilesでAnsibleを使っていてansible-lintも入れていた(v5)

v6に上げるとそもそも実行できないなどの問題が発生したのでしばらく上げてなかったが重い腰を上げて対応した

色々変更したので作業ログを残しておく、どこかの誰かの参考程度にでもなれば嬉しい…

実行環境のバージョン

$ ansible-lint --version
ansible-lint 6.17.0 using ansible-core:2.15.0 ruamel-yaml:0.17.31 ruamel-yaml-clib:0.2.7
Python 3.10.6  

v6に上げて実行してみる

WARNING Listing 488 violation(s) that are fatal

途方もない…

自動修正

$ ansible-lint --write hoge.yml

--writeオプションを渡すことで対象のファイルと、関連するroleなどのファイルも修正してくれる

自動修正後の警告

WARNING  Listing 147 violation(s) that are fatal

かなり減った

  • 自動修正の内容が分かるPR

feature/migration ansible lint v6 by swfz · Pull Request #794 · swfz/dotfiles

ansibleを実行できるところまでエラーを潰していく

lintだけだし大丈夫かなと思ったら怒られた

include

ERROR! this task 'ansible.builtin._include' has extra params, which is only allowed in the following modules: ansible.legacy.import_role, ansible.builtin.shell, ansible.legacy.win_command, ansible.legacy.add_host, import_role, ansible.legacy.include_tasks, raw, meta, ansible.legacy.meta, group_by, ansible.windows.win_command, ansible.builtin.set_fact, ansible.legacy.script, ansible.builtin.include_role, ansible.builtin.script, ansible.legacy.include_role, ansible.legacy.include, ansible.builtin.win_shell, ansible.builtin.import_role, include_role, ansible.builtin.win_command, ansible.legacy.command, ansible.windows.win_shell, ansible.builtin.group_by, command, ansible.legacy.include_vars, ansible.builtin.add_host, ansible.builtin.include_tasks, ansible.legacy.set_fact, win_shell, ansible.legacy.import_tasks, ansible.builtin.include_vars, script, include_tasks, ansible.builtin.raw, ansible.builtin.import_tasks, shell, win_command, include_vars, set_fact, ansible.builtin.meta, ansible.builtin.command, ansible.legacy.raw, include, ansible.builtin.include, import_tasks, ansible.legacy.group_by, ansible.legacy.shell, add_host, ansible.legacy.win_shell

The error appears to be in '/usr/local/src/ansible/roles/git/tasks/main.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

---
- name: Debian tasks
  ^ here

--writeオプションでモジュールの指定をFCQNへ変換してくれたようだが、includeは対応されてなかった模様

変換したら_includeになっていたがそもそもないよって話っぽい、自動書き換えができないものに関しては_付けるようになっているのかも?

移行先としてはinclude_tasks,include_varsなどがあるみたいだったが今回はinclude_tasksが適切そうだったので手で書き換えた

  • 差分
 - name: Redhat tasks
-   ansible.builtin._include: redhat.yml
+   ansible.builtin.include_tasks: redhat.yml
   when: ansible_os_family == 'RedHat'

handlerへの通知指定

--writeで各設定ファイル中のnameの値は1文字目を大文字にするというルールが適用された

その結果、handlerで指定するタスク名が変更されずに「ないよ!」というエラーが発生した

  • tasks/main.yml
 - name: Set config
   ansible.builtin.template: src=smb.conf dest=/etc/samba/smb.conf mode=0644
   register: samba_config
-   notify: restart samba
+   notify: Restart samba
  • handlers/main.yml
---
- name: Restart samba
  ansible.builtin.service: name=smb state=restarted
  when: ansible_env.get('CI', None) and ansible_env.CI != "true"

最初の文字大文字推奨するんであればこの辺も対応してよ…って感じはするが

expected input

  • anyenv/tasks/main.yml
   ansible.builtin.expect:
     command: "{{ ansible_env.HOME }}/.anyenv/libexec/anyenv install --init"
     responses:
-      .*Do you want to checkout.*: true
+      '.*Do you want to checkout.*': y

--writeオプションで書き換えられてたので戻した

ansible-lintの設定を見る

設定ファイルのドキュメント

この辺読みつつ対応する

Configuration - Ansible Lint Documentation

ansible-lint.readthedocs.io

出力フォーマット

$ ansible-lint -f json ubuntu.yml > lint.json

jsonフォーマットもしくはsarifフォーマットじゃないと詳しい情報が出てこない

  • pep8フォーマット
centos.yml:2: name[play]
centos.yml:32: yaml[comments]

なるほど…

  • jsonフォーマット
[
  {
    "type": "issue",
    "check_name": "name[play]",
    "categories": [
      "idiom"
    ],
    "url": "https://ansible-lint.readthedocs.io/rules/name/",
    "severity": "major",
    "description": "All plays should be named.",
    "fingerprint": "5493323e150e33e04cd3e881e653620fcb888eade98f89d020f35fc837272cee",
    "location": {
      "path": "centos.yml",
      "lines": {
        "begin": 2
      }
    }
  },
  {
    "type": "issue",
    "check_name": "yaml[comments]",
    "categories": [
      "formatting",
      "yaml"
    ],
    "url": "https://ansible-lint.readthedocs.io/rules/yaml/",
    "severity": "major",
    "description": "Too few spaces before comment",
    "fingerprint": "fac9d557e84fefa8205a6aec84c3749120882c6d54f90889c945f349afc1959f",
    "location": {
      "path": "centos.yml",
      "lines": {
        "begin": 32
      }
    }
  },

既存の警告をignoreする

とりあえず、動かすところを目的としたいので、すべてIgnoreに放り込んで少しずつ対応できるようにする

$ ansible-lint --nocolor centos.yml codespace.yml mac.yml ubuntu.yml > lint.txt
$ cat lint.txt | awk -F"[: ]" '{print $1 " " $4}' | sort | uniq > .ansible-lint-ignore

これで

  • .ansible-lint-ignore
centos.yml yaml[comments]
roles/actionlint/tasks/main.yml var-naming[no-role-prefix]
roles/actionlint/tasks/main.yml yaml[comments]

こんな感じになる

この状態でlintを実行すると次のようになる

$ ansible-lint  centos.yml codespace.yml mac.yml ubuntu.yml
WARNING  Listing 140 violation(s) marked as ignored, likely already known
centos.yml:33: yaml[comments] (warning)
roles/actionlint/tasks/main.yml:2: var-naming[no-role-prefix] (warning)
roles/actionlint/tasks/main.yml:2: yaml[comments] (warning)
roles/actionlint/tasks/main.yml:10: var-naming[no-role-prefix] (warning)

検知はしているがignoreしているよというメッセージが出力される

marked as ignored, likely already known ということで終了コードは0になる(fatal errorが存在する場合は終了コード2だった)

既存の警告の解消

yaml[comments]

コメントの前に2つ以上スペース入れろってやつ

--writeで自動修正したやつすべて警告対象になってた

自動修正とは?…

  • 修正PR

feature/ansible lint comments by swfz · Pull Request #796 · swfz/dotfiles

var-naming[no-role-prefix]

変数はroleのprefixを入れろって言っている

ツールのバージョンチェックをする箇所で同じような命名規則にしていたのですべて警告対象になった

  • 修正差分(role名: actionlint)
   ansible.builtin.shell: command -v actionlint
   environment:
     PATH: /usr/local/bin:{{ ansible_env.PATH }}
-  register: exist_actionlint
+  register: actionlint_exist
   changed_when: false
   ignore_errors: true


   ansible.builtin.shell: actionlint --version | head -n 1
   environment:
     PATH: /usr/local/bin:{{ ansible_env.PATH }}
-  register: version_in_actionlint
+  register: actionlint_current_version
   changed_when: false
   ignore_errors: true
-  when: exist_actionlint.rc == 0
+  when: actionlint_exist.rc == 0

 - block:
     - name: Get tar.gz

     - name: Install
       changed_when: true
       ansible.builtin.command: mv /tmp/actionlint /usr/local/bin/actionlint
-  when: exist_actionlint.rc != 0 or ( version_in_actionlint is defined and version_in_actionlint.stdout.find(actionlint_version) == -1 )
+  when: actionlint_exist.rc != 0 or ( actionlint_current_version is defined and actionlint_current_version.stdout.find(actionlint_version) == -1 )

他にも結構量があったのでsedで書き換えたい

lint.txtはpep8フォーマットで出力したファイル

cat lint.txt | grep no-role-prefix | awk -F":" '{print $1}' | uniq | xargs sed -i 's/\(exist\)_\([a-z]*\)/\2_\1/g'
cat lint.txt | grep no-role-prefix | awk -F":" '{print $1}' | uniq | xargs sed -i 's/\(version_in\)_\([a-z]*\)/\2_current_version/g'

いくつか命名規則に沿っていないものもあったので手動で修正した

  • 修正PR

feature/ansible lint var naming by swfz · Pull Request #797 · swfz/dotfiles

name[missing]

blockにもnameが必要らしい

  • 対象PR

feature/ansible lint name missing by swfz · Pull Request #798 · swfz/dotfiles

key-order[task]

key-order - Ansible Lint Documentation

キー名のルール

  • nameは一番初めにしないといけない
  • block,rescue,alwaysは最後にしないといけない

  • 対象PR

feature/ansible lint key order by swfz · Pull Request #799 · swfz/dotfiles

no-free-form

1行に色々パラメータ含めて書くなってやつ

     - name: Configure make install jo
-      ansible.builtin.command: chdir=/tmp/{{ jo.dir }} {{ item }}
+      ansible.builtin.command:
+        chdir: /tmp/{{ jo.dir }}
+        cmd: "{{ item }}"
       changed_when: true
       with_items:
         - ./configure

キーによって変数はクオートしないといけない? っぽいのがある模様

適切なクオートができていないと次のように構文エラーとなってしまい解析できなかった

ansible-lint roles/jo/tasks/main.yml
WARNING  Listing 1 violation(s) that are fatal
roles/jo/tasks/main.yml:1: load-failure[runtimeerror]

少し詰まった

  • 対象PR

feature/ansible lint no free form by swfz · Pull Request #801 · swfz/dotfiles

risky-file-permission

risky-file-permissions - Ansible Lint Documentation

get_urlなどで取得できるファイルのpermissionを明示的に指定しろって話っぽい

  • 対象PR

feature/ansible lint risky file permission by swfz · Pull Request #800 · swfz/dotfiles

no-changed-when

no-changed-when - Ansible Lint Documentation

コマンド系のモジュール使用時に、changedにする条件を指定する

  • 対象PR

feature/ansible lint no changed when by swfz · Pull Request #802 · swfz/dotfiles

command-instead-of-shell

command-instead-of-shell - Ansible Lint Documentation

それ本当にshell使う必要あるの?ってやつ

環境変数の拡張やパイプを使った複数のコマンドの連結などを使わない場合はcomandにしてねという感じ

command-instead-of-module

command-instead-of-module - Ansible Lint Documentation

それコマンドじゃなくてモジュールでできるよね?ってやつ

  • 対象PR

feature/ansible lint command instead of module by swfz · Pull Request #806 · swfz/dotfiles

jinja[spacing]

jinja - Ansible Lint Documentation

jinjaテンプレートで記述する箇所に適切なスペースをいれてねというやつ

  • 対象PR

feature/ansible lint jinja by swfz · Pull Request #808 · swfz/dotfiles

おわり

つかれた