koh’s blog

Sys Admin who loves automation

TestinfraとAnsibleを組み合わせて使う

For English

インフラテストツールのTestinfraをAnsibleと組み合わせて使用すると色々と捗るよという投稿です。
Testinfraについては以前ブログを書いているので見ていただければと。

koh-sh.hatenablog.com

Inventoryの共有

TestinfraはAnsibleのInventoryの情報を参照することができます。
そのためAnsibleで管理している情報をそのままテストへ活用できます。

https://testinfra.readthedocs.io/en/latest/backends.html#ansible

$ py.test --hosts='ansible://all' # tests all inventory hosts
$ py.test --hosts='ansible://host1,ansible://host2'
$ py.test --hosts='ansible://web*'
$ py.test --force-ansible --hosts='ansible://all'
$ py.test --hosts='ansible://host?force_ansible=True'

Inventoryファイルをansible.cfg等で設定せずにオプションで指定する場合には--ansible-inventory=ANSIBLE_INVENTORYで指定できます。

Ansibleのmoduleの実行

Testinfraのテストの中でAnsibleのmoduleを実行することができます。

https://testinfra.readthedocs.io/en/latest/modules.html#ansible

[koh@kohs-MBP] ~/vag_test
% ipython
Python 3.7.3 (default, May  1 2019, 16:07:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import testinfra

In [2]: host = testinfra.get_host("ansible://Vag1")

In [3]: host.ansible("command", "echo foo", check=False)
Out[3]:
{'ansible_facts': {'discovered_interpreter_python': '/usr/bin/python'},
 'changed': True,
 'cmd': ['echo', 'foo'],
 'delta': '0:00:00.004734',
 'end': '2019-10-05 15:07:42.251008',
 'rc': 0,
 'start': '2019-10-05 15:07:42.246274',
 'stderr': '',
 'stderr_lines': [],
 'stdout': 'foo',
 'stdout_lines': ['foo']}

In [4]:

こちらはcommandモジュールを実行してみた例です。
実行した結果としてchangedやrc, stdout等Ansibleで実行したときと同様のデータが帰ってきます。

setupモジュールを使用するテストとしては下記のようなイメージでしょうか。

[koh@kohs-MBP] ~/vag_test
% cat test_ansible.py
def test_dns(host):
    nameservers = host.ansible("setup")["ansible_facts"]["ansible_dns"]["nameservers"]
    assert '10.1.1.1' in nameservers
[koh@kohs-MBP] ~/vag_test
% 
[koh@kohs-MBP] ~/vag_test
% py.test -v test_ansible.py --hosts='ansible://Vag1'
======================================== test session starts ========================================
platform darwin -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.9.0 -- /Users/koh/.pyenv/versions/3.7.3/bin/python3.7
cachedir: .pytest_cache
rootdir: /Users/koh/vag_test, inifile: pytest.ini
plugins: xonsh-0.8.12, testinfra-3.0.5
collected 1 item

test_ansible.py::test_dns[ansible://Vag1] FAILED                                              [100%]

============================================= FAILURES ==============================================
_____________________________________ test_dns[ansible://Vag1] ______________________________________

host = <testinfra.host.Host object at 0x10e9be748>

    def test_dns(host):
        nameservers = host.ansible("setup")["ansible_facts"]["ansible_dns"]["nameservers"]
>       assert '10.1.1.1' in nameservers
E       AssertionError: assert '10.1.1.1' in ['10.0.2.3']

test_ansible.py:3: AssertionError
===================================== 1 failed in 2.17 seconds ======================================
zsh: exit 1     py.test -v test_ansible.py --hosts='ansible://Vag1'
[koh@kohs-MBP] ~/vag_test
%

setupの結果からnameserverの情報を取得しテストすることができました。

Variableの共有

Ansible側で定義されているVariableを参照できます。
参照できる変数はhost_varsとgroup_varsで定義されているものとinventory_hostname等の一部の変数です。
Playbook内でinclude_vars等で定義しているものは参照できないのでご注意ください。

[koh@kohs-MBP] ~/vag_test
% ipython
Python 3.7.3 (default, May  1 2019, 16:07:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import testinfra

In [2]: host = testinfra.get_host("ansible://Vag1")

In [3]: host.ansible.get_variables()
Out[3]:
{'aaa': 'bbb',
 'foo': 'bar',
 'hoge': 'fuga',
 'inventory_hostname': 'Vag1',
 'group_names': ['Vag'],
 'groups': {'Vag': ['Vag1', 'Vag2', 'Vag3'], 'all': ['Vag1', 'Vag2', 'Vag3']}}

In [4]:

まとめ

現在MoleculeでもTestinfraがデフォルトのテストツールとして採用されているように、かなりAnsibleとの相性がいいと感じました。
Testinfraは他にもDockerやKubenatesとも組み合わせることができるので色々と試していきたいです。

GitHub ActionsでmacOS用のPlaybookをテストする

以前書いた記事の続きです。
前回AnsibleのPlaybookのlintをGitHub Actionsで実施するところまで設定したので実際にPlaybookを実行してテストをさせるようにしました。

koh-sh.hatenablog.com

使用しているリポジトリはこちらです。

github.com

Playbook実行

GitHub Actionsの定義ファイルの/.github/workflows/ansiblelint.ymlansibletest.ymlにリネームした上で下記を3行追記しました。

- name: Ansible lint
+ name: Ansible test

 on: [push]

 @@ -26,3 +26,6 @@ jobs:
       run: |
         ansible-playbook site.yml --syntax-check
         ansible-lint site.yml
+    - name: run playbook
+       run: |
+         ansible-playbook site.yml

実行させるための設定は以上です。
次にコミットされると自動でansibleインストール, lint, Playbook実行まで行われます。

ちなみに使用しているPlaybookですが実際に1から実行したことがなく、現在使用している端末の設定を少しずつ書き起こしたものだったので最後まで実行しきるまでかなりエラーが出ました。

こちらのP/Rがその四苦八苦した結果です。

github.com

パッケージのインストールに時間がかかるのでコメントして省略しようとしたら後続タスクでエラーが出たり、destのパスが見つからなくてlsして探したりと我ながらひどかったです。
Github Actionsのデバッグのコツとかあるんですかね。

テスト実行

Playbook実行後のテストも追加しました。
テスト実装の仕方は色々ありますが、特に深く考えずtestinfraでつらつら書きました。
testinfraについては過去にブログで記事を書いたのでよろしければご覧くださいませ。

koh-sh.hatenablog.com

各roleごとにtestsディレクトリを作成し、その下にtestファイルを置きました。

例としてzsh設定role用のテストはこのような感じになります。

/roles/zsh/tests/test_zsh.py (クリックで展開)

import os


def test_shells_file(host):
    shells = host.file("/etc/shells")
    assert shells.contains("/usr/local/bin/zsh")


def test_ccat_completion(host):
    compfile = "/usr/local/share/zsh/site-functions/_ccat"
    assert host.file(compfile).is_file

roleごとのtestを作成したらGitHub Actionsの定義も合わせて修正していきます。
修正内容としてはこちらになります。

  • インストールの際にtestinfra, pycodestyleをインストール
  • テストコードに対してpycodestyle実行(lint)
  • testinfra実行

※ pycodestyleはpythonコードがpep8に準拠しているかのチェックツールです。

github.com

そして完成したansibletest.ymlがこちらになります。

/.github/workflows/ansibletest.yml (クリックで展開)

name: Ansible test

on: [push]

jobs:
  build:

    runs-on: macOS-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: [2.7, 3.7]
        ansible-version: [2.7.13, 2.8.5]

    steps:
    - uses: actions/checkout@v1
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v1
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Ansible ${{ matrix.ansible-version }}
      run: |
        python -m pip install --upgrade pip
        pip install pycodestyle testinfra ansible-lint ansible==${{ matrix.ansible-version }}
    - name: Lint playbook
      run: |
        ansible-playbook site.yml --syntax-check
        ansible-lint site.yml
    - name: run playbook
      run: |
        ansible-playbook site.yml
    - name: run tests
      run: |
        pycodestyle -v roles
        py.test -v roles 

pycodestyleもtestinfra(py.test)もディレクトリを引数にするとそのディレクトリ配下から対象のファイルを探してテスト実行してくれるのでrolesディレクトリをまるっと指定しています。

これでコミットごとにAnsibleインストールから実行後のテストまで自動で実施されるようになりました。
直近のコミットでのテストはこんな感じになります。

version up ansible · koh-sh/macbook-playbook@6953381 · GitHub

まとめ

実際にmacセットアップ用のPlaybookに対してここまでがっつりCIでテストする必要はないような気がしますがGitHub Actions楽しいので良しとします。

iPhone移行メモ

iPhone11を購入してiPhone7から移行したので自分用メモ。

環境

機種及びOSのバージョン

機種 OS
iPhone11 (新) iOS13.0
iPhone7 (旧) iOS13.0
Apple Watch3 watchOS5.3.1

データ移行

iOS 12.4以降であれば旧iPhoneから新iPhoneへ直接データを転送できる。
iPhoneを起動すると旧iPhoneに案内が出るのでそのまま指示通りに操作すると転送が始まる。
だいたい20分くらいで転送は完了した。転送中は両方のiPhoneが使用できないので注意。

f:id:koh-sh:20190923203548j:plain

ほとんどはこのデータ転送で完了する。
ログイン情報やダウンロードコンテンツの情報も含め。
ただしいくつかは別途移行する。

Apple Pay

クレジットカード情報は手動で移行する必要がある。
新旧両方のiPhoneに重複しても問題ないのでいつもどおりカード情報を新iPhoneに登録してあげればOK

Suica + Apple Watchのペアリング

Apple Payのクレジットカードは新旧両方での重複登録が可能だが、Suicaはできない。
SuicaApple Watch側のApple Payに登録しているのでApple Watchのペアリングも合わせて実施。

Apple WatchからSuicaの紐付け解除

iPhonewatchアプリ -> Wallet & Apple Pay -> Suica -> Remove This Card

iPhoneからApple Watchのペアリング解除

iPhonewatchアプリ -> Apple watch -> Unpair Apple watch

iPhoneSuica登録

watchに直接登録もできそうだけど今回はこっちでやった。

iPhoneのsetting -> Wallet & Apple Pay -> add card -> suica

iPhoneApple Watch ペアリング

iPhoneとのペアリングが解除されたあとに再度ペアリングのプロンプトが出るので新iPhoneですすめる。
10分くらいかかった。

iPhoneからApple WatchSuica移行

iPhonewatchアプリ -> Wallet & Apple Pay -> other card on your phoneのSuicaをadd

Line移行

Lineも手動での移行が必要。

トーク履歴バックアップ (事前にやっておく)

iPhoneのLineアプリ -> 設定 -> chats -> chat history backup ※リストアは勝手にされるっぽい?

iPhoneのLineでtransfer許可

iPhoneのLineアプリ -> 設定 -> Account Transfer -> Allow Account Transfer

iPhoneのLineでログイン

email + passwordが必要

lineモバイルのプロファイル設定

lineモバイルはプロファイルの設定が必要

Simカード差し替え

プロファイル設定

下記リンク参考にインストールする。

mobile.line.me

まとめ

おそらくこれですべて完了。漏れがあれば都度追記。
だいぶやること少なくなってていいですね。

Github Actionsでansible-lintを自動で実施する

For English

申し込んでいたGithub Actionsのbetaが使えるようになったのでAnsibleのsyntax checkとlintをさせてみようと思います。
なお本記事の内容は2019年9月7日時点のものであり、今後変更される可能性があります。

設定

公式ドキュメントを適宜参照しながら作業を進めていきます。

Automating your workflow with GitHub Actions - GitHub Help

とりあえず動かす

今回は私個人で使用しているmacbookのセットアップ用のPlaybookのリポジトリに設定していきます。
github.com

Actionsの項目が増えているのでこちらを選択します。
f:id:koh-sh:20190907163335p:plain

いろんなworkflowのテンプレートが選択できるので、今回はpython packageを使用します。
クリックするとworkflowの定義ファイルの修正画面に遷移するので下記のように修正します(ファイル名も修正しました)。

.github/workflows/ansiblelint.yml(クリックで展開)

name: Ansible lint

  on: [push]

  jobs:
   build:

      runs-on: macOS-latest
     strategy:
       max-parallel: 4
       matrix:
         python-version: [2.7, 3.5, 3.6, 3.7]

      steps:
     - uses: actions/checkout@v1
     - name: Set up Python ${{ matrix.python-version }}
       uses: actions/setup-python@v1
       with:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
         pip install ansible ansible-lint
     - name: Lint playbook
       run: |
         ansible-playbook site.yml --syntax-check
         ansible-lint site.yml

macos用のplaybookなのでruns-onをmacOS-latestにしてみます。
流れとしては下記になります。

  • pipでansibleとansible-lintをインストール
  • ansible-playbookの--syntax-checkオプションをつけて実行
  • ansible-lint実行

これでcommitすると自動でテストが走ります。
再度Actionsを見てみるとテストの結果が見られます。
f:id:koh-sh:20190907164722p:plain

create github action workflow for ansible lint · koh-sh/macbook-playbook@3daeb98 · GitHub

python-versionが4つでmax-parallelを4にしているので4種類のテストが並行して実施されます。
リソースの上限についてはDocumentを確認ください。
https://help.github.com/en/articles/workflow-syntax-for-github-actions#usage-limits

各バージョンのbuildの各工程をクリックすると詳細が見られます。
今回はansible-lintでエラーが出ているのでテストに失敗しています。

テスト成功パターン

ansible-lintでエラーが出ているので下記commitでエラーを消します。
文末の余計なスペースを消すのと、shellモジュールの箇所は必要なので.ansible-lintを置いて除外してあげます。

github.com

masterブランチに直接pushしていますがちゃんと自動でテストは実施されます。
f:id:koh-sh:20190907170056p:plain

fix 201 and skip 305 · koh-sh/macbook-playbook@577519c · GitHub

テストはすべて問題なく完了しました。
f:id:koh-sh:20190907170209p:plain

ちなみにcommitログからもテスト成功失敗がわかるようになります。

プルリクエストも試す

プルリクエストを送る際の挙動も見てみます。
github.com

適当なPRを作成するとテストが実行されPRの画面から結果が確認できます。
f:id:koh-sh:20190907171027p:plain

ちなみにslackとgithubを連携させていて、PRの場合テストの結果もslackに通知されました。
Slack + GitHub

f:id:koh-sh:20190907171556p:plain masterへの直接pushだとテスト結果は表示されませんでした。
何か追加の設定が必要かもしれないですが確認できていないです。

複数バージョンのAnsibleでテストする

今の設定だとpythonの4つのバージョンで最新版のAnsibleのテストをしています。
これをpythonの2系、3系とAnsibleの2.7系、2.8系の組み合わせのテストをするように変更してみます。

workflowの定義ファイルを下記のように修正してみます。

.github/workflows/ansiblelint.yml(クリックで展開)

name: Ansible lint

on: [push]

jobs:
  build:

    runs-on: macOS-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: [2.7, 3.7]
        ansible-version: [2.7.13, 2.8.4]

    steps:
    - uses: actions/checkout@v1
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v1
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Ansible ${{ matrix.ansible-version }}
      run: |
        python -m pip install --upgrade pip
        pip install ansible-lint ansible==${{ matrix.ansible-version }}
    - name: Lint playbook
      run: |
        ansible-playbook site.yml --syntax-check
        ansible-lint site.yml

これでpushするとテスト内容が修正され、うまく目論見通りに動きました。
f:id:koh-sh:20190907172837p:plain

to test with multiple version of ansible · koh-sh/macbook-playbook@0ffab4e · GitHub

まとめ

無事にGithub Actionsでansible-lintを実行できました。
この記事にある内容は大体1時間程度ですべて試せました。かなりシンプルで直感的です。
テスト以外にもdeploy等もGithub Actionsでできるみたいなので積極的に試していきたいです。

持っている技術書の一覧をgithubで管理し始めた

概要

最近kindleで技術書を買うことが増えたので物理と電子で持っている本を一覧化してみました。

ちなみに作成したリポジトリはこちらです。

github.com

とりあえずREADMEにマークダウンで書いてます。
フォーマット等は今後少しづつ直していこうかなと。

期待する効果

始めたばかりなので予想ですがこんな効果がありそうです。

自身の学習履歴の客観視

当たり前の部分ですが、これまでは技術書が本棚とスマホタブレット等の端末に点在していたが一箇所にまとめることで客観視がしやすくなります。
またgitのcommitログを見ればいつどの本を買って読み終わるまでどのくらいかかったなども記録できそうです。

モチベーションアップ

私の場合ですがもともと読書が苦手で、実際一覧にステータスをつけてみると読みかけや手つかずの本も結構ありました。(STATUSがREADINGとUNREAD)
そういった部分を可視化することでモチベーションアップにつながるかなと期待しています。

興味の可視化

持っている技術書の一覧は自分が持っているスキルの一覧にはなかなかなりにくいですが、自分が興味がある技術分野の一覧にはなると思います。
自分がどんなエンジニアなのかを表す一つの指標になるんじゃないかなと思います。

まとめ

まだまだ読んでいる本が少ないことも改めて可視化されたので、3日坊主にならないようにしたい。