Ansible のCommand Modules を触ってみた

目的

Ansible にあるたくさんのモジュールの中からよく使われそうなモジュールを使ってみて知見を得る

環境

Microsoft Azure Cloud Shell
Ubuntu 16.04.4 LTS

Ansible のバージョン

kono@Azure:~/ansible_pj$ ansible --version
ansible 2.5.2
  config file = None
  configured module search path = [u'/home/kono/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/ansible/local/lib/python2.7/site-packages/ansible
  executable location = /opt/ansible/bin/ansible
  python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
kono@Azure:~/ansible_pj$

予めしておくこと

Ansible による構成対象の VMssh ログイン出来るように Cloud Shell の公開鍵を登録することです。おそらく VM を作るときに聞いてくると思いますが。。。すみません確認して追記します。

Commands modules

Commands modules — Ansible Documentation

まずは Commands modules から見ていく

command

command_module.yaml を作成

$ cat command_modules.yaml
# Command modules test
- hosts: any
  user: takashi
  tasks:
    - name: return distribution
      command: cat /etc/lsb-release
    - name: return df
      command: df -h
    - name: return memory free
      command: free
    - name: return inodes info
      command: df -i
    - name: ip address
      command: ip a
    - name: list of listened ports
      command: netstat -nlt

実行してみる

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts command_modules.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.70.39]

TASK [return distribution] ******************************************************************************************************************************************************************************************************************
changed: [40.74.70.39]

TASK [return df] ****************************************************************************************************************************************************************************************************************************
changed: [40.74.70.39]

TASK [return memory free] *******************************************************************************************************************************************************************************************************************
changed: [40.74.70.39]

TASK [return inodes info] *******************************************************************************************************************************************************************************************************************
changed: [40.74.70.39]

TASK [ip address] ***************************************************************************************************************************************************************************************************************************
changed: [40.74.70.39]

TASK [list of listened ports] ***************************************************************************************************************************************************************************************************************
changed: [40.74.70.39]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.70.39                : ok=7    changed=6    unreachable=0    failed=0

kono@Azure:~/ansible_pj$

実行されているような気がしますね。では、デバッグメッセージのオプションを使ってみましょう

$ ansible-playbook -i hosts command_modules.yaml -vvv
上記のように、 -vvv オプションをつけることで詳細なメッセージを確認できます。 v の数が何個かで出力レベルがわかるので、自分の欲しい情報が何か整理してから使っても良いかも。基本とりあえず -vvv で。という感じなんだと妄想してみる。

ちなみに、ソースコードを確認してみる

https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/commands/command.py

https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/commands/command.py#L137-L145

このあたりで色々定義しているのがわかる

expect

https://docs.ansible.com/ansible/latest/modules/expect_module.html#expect-module

先に書きますが、私の環境では上手く行きませんでした。

以下は参考までにどうぞ。
まず、適当に playbook を書いてみた。
expect.yaml

kono@Azure:~/ansible_pj$ cat expect.yaml
- hosts: any
  user: takashi
  tasks:
    - name: expect module test
      expect:
        command: /usr/bin/python3 /home/takashi/input_test.py
        responses:
          'please input something: ' : 'This is expect module test'
kono@Azure:~/ansible_pj$

expect というくらいなので、ターミナルに何かコメントがあって、入力待ち状態になる時にこれを使うはず。
というわけで、ssh 先の VM に python3 で適当にコードを書いてみた。

takashi@test1:~$ cat input_test.py 
#!/usr/bin/python3
# coding: utf-8

tmp = input("please input something: ")
print(tmp)

takashi@test1:~$ 

で、実行

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts expect.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.95.98]

TASK [expect module test] *******************************************************************************************************************************************************************************************************************
fatal: [40.74.95.98]: FAILED! => {"changed": false, "msg": "The pexpect python module is required"}
        to retry, use: --limit @/home/kono/ansible_pj/expect.retry

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.95.98                : ok=1    changed=0    unreachable=0    failed=1

kono@Azure:~/ansible_pj$ 

失敗した。
メッセージには、 The expected python module is required とある。
このモジュールを使うためには、 pexpect が必須なんですね。
公式のドキュメントにも書いてありました。

expect - Executes a command and responds to prompts. — Ansible Documentation

ということで、 pexpect が入っているか確認します。

kono@Azure:~/ansible_pj$ ansible --version
ansible 2.5.2
...
  python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
kono@Azure:~/ansible_pj$ pip2
pip2    pip2.7
kono@Azure:~/ansible_pj$ pip2.7 list | grep pexpect
kono@Azure:~/ansible_pj$

ない!

pexpect のインストールですね。 やってみましょう。

kono@Azure:~/ansible_pj$ pip2.7 install pexpect
Collecting pexpect
  Using cached https://files.pythonhosted.org/packages/89/e6/b5a1de8b0cc4e07ca1b305a4fcc3f9806025c1b651ea302646341222f88b/pexpect-4.6.0-py2.py3-none-any.whl
Collecting ptyprocess>=0.5 (from pexpect)
  Using cached https://files.pythonhosted.org/packages/d1/29/605c2cc68a9992d18dada28206eeada56ea4bd07a239669da41674648b6f/ptyprocess-0.6.0-py2.py3-none-any.whl
Installing collected packages: ptyprocess, pexpect
Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/ptyprocess-0.6.0.dist-info'
Consider using the `--user` option or check the permissions.

kono@Azure:~/ansible_pj$ 

??? 何かおかしい。 Permissiono denied ですと!?
--user オプションを使ってみましょう。書いてあるとおり。

kono@Azure:~/ansible_pj$ pip2.7 install pexpect --user
Collecting pexpect
  Using cached https://files.pythonhosted.org/packages/89/e6/b5a1de8b0cc4e07ca1b305a4fcc3f9806025c1b651ea302646341222f88b/pexpect-4.6.0-py2.py3-none-any.whl
Collecting ptyprocess>=0.5 (from pexpect)
  Using cached https://files.pythonhosted.org/packages/d1/29/605c2cc68a9992d18dada28206eeada56ea4bd07a239669da41674648b6f/ptyprocess-0.6.0-py2.py3-none-any.whl
Installing collected packages: ptyprocess, pexpect
Successfully installed pexpect-4.6.0 ptyprocess-0.6.0
kono@Azure:~/ansible_pj$
kono@Azure:~/ansible_pj$ pip2.7 list | grep pexpect
pexpect    4.6.0
kono@Azure:~/ansible_pj$

あっさり解決。。。ちゃんと入った。
ということで、リトライします。

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts expect.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.95.98]

TASK [expect module test] *******************************************************************************************************************************************************************************************************************
fatal: [40.74.95.98]: FAILED! => {"changed": false, "msg": "The pexpect python module is required"}
        to retry, use: --limit @/home/kono/ansible_pj/expect.retry

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.95.98                : ok=1    changed=0    unreachable=0    failed=1

kono@Azure:~/ansible_pj$

??? 同じエラーが出てしましました。 モジュールが必要だったのは、もしかすると、VM の方だったのかな?
本当は pip のインストール及び、 pexpect のインストールも Ansible で実施したかったけど、本質じゃないので普通に apt-get install python3-pip で実施することにした。

takashi@test1:~$ pip3 -V
pip 1.5.4 from /usr/lib/python3/dist-packages (python 3.4)
takashi@test1:~$

しかし、 pip3 がインストールできたので、 pexpext のインストールを Ansible でやってみる。

kono@Azure:~/ansible_pj$ cat python_modules.yaml
# Command modules test
- hosts: any
  user: takashi
  become: true
  tasks:
    - name: install pexpect
      command: /usr/bin/pip3 install pexpect
kono@Azure:~/ansible_pj$

プレイブックが出来たので、実行してみる

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts python_modules.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.95.98]

TASK [install pexpect] **********************************************************************************************************************************************************************************************************************
changed: [40.74.95.98]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.95.98                : ok=2    changed=1    unreachable=0    failed=0

kono@Azure:~/ansible_pj$

お。出来てそう。VM で確認してみる。

takashi@test1:~$ pip3 list | grep pexpect
pexpect (4.6.0)
takashi@test1:~$ 

入りました。
ようやく準備が出来たので、 expect をもう一度試してみる。

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts expect.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.95.98]

TASK [expect module test] *******************************************************************************************************************************************************************************************************************
fatal: [40.74.95.98]: FAILED! => {"changed": false, "msg": "The pexpect python module is required"}
        to retry, use: --limit @/home/kono/ansible_pj/expect.retry

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.95.98                : ok=1    changed=0    unreachable=0    failed=1

kono@Azure:~/ansible_pj$

それでもダメだった。。。んー、何がいけなかったのか。。。
テスト
AzureCloud Shell 環境での動作について

https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/commands/expect.py#L95-L99

ここでやっていることと同じことをしてみる。

python2.7 の場合の import pexpect のテスト

kono@Azure:~/ansible_pj$ python2.7
Python 2.7.12 (default, Dec  4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> try:
...     import pexpect
...     print(True)
... except ImportError:
...     print(False)
...
True
>>>

OK 問題ない。

kono@Azure:~/ansible_pj$ python
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> try:
...     import pexpect
...     print(True)
... except ImportError:
...     print(False)
...
False
>>>

pexpect がインポート出来ていない。
もう一度、確認。

kono@Azure:~/ansible_pj$ ansible --version
ansible 2.5.2
  config file = None
  configured module search path = [u'/home/kono/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/ansible/local/lib/python2.7/site-packages/ansible
  executable location = /opt/ansible/bin/ansible
  python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
kono@Azure:~/ansible_pj$

executable location に実行ファイルがありそうだ。

kono@Azure:~/ansible_pj$ ls -l /opt/ansible/bin/ | grep python
...
lrwxrwxrwx  1 root root       7 Jun 15 19:04 python -> python2
-rwxr-xr-x 11 root root 3492656 Jun 15 19:04 python2
lrwxrwxrwx  1 root root       7 Jun 15 19:04 python2.7 -> python2
...
kono@Azure:~/ansible_pj$

おお。 python2 に全て集約されている!!
pip 系はどうだろう?

kono@Azure:~/ansible_pj$ ls -l /opt/ansible/bin/ | grep pip
-rwxr-xr-x 11 root root     224 Jun 15 19:04 pip
-rwxr-xr-x 11 root root     224 Jun 15 19:04 pip2
-rwxr-xr-x 11 root root     224 Jun 15 19:04 pip2.7
kono@Azure:~/ansible_pj$

pip 系はそのままなんだろうか。。。それぞれのバージョンを見てみよう。

kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip -V
pip 10.0.1 from /opt/ansible/local/lib/python2.7/site-packages/pip (python 2.7)
kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip2 -V
pip 10.0.1 from /opt/ansible/local/lib/python2.7/site-packages/pip (python 2.7)
kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip2.7 -V
pip 10.0.1 from /opt/ansible/local/lib/python2.7/site-packages/pip (python 2.7)
kono@Azure:~/ansible_pj$

全部同じ出力である。同じ所を参照しているので問題なさそう。
pip に関して問題ないことがわかったので、 python2import pexpect テストを実施してみよう

kono@Azure:~/ansible_pj$ /opt/ansible/bin/python2
Python 2.7.12 (default, Dec  4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> try:
...   import pexpect
...   print True
... except ImportError:
...   print False
...
False
>>>

なんだと。。。 python2 の起動 path が違うから別物を使っていたということか???

kono@Azure:~/ansible_pj$ whereis python2.7
python2: /usr/bin/python2.7 /usr/bin/python2 /usr/bin/python2.7-config /usr/lib/python2.7 /etc/python2.7 /usr/local/lib/python2.7 /usr/include/python2.7 /opt/ansible/bin/python2.7 /opt/ansible/bin/python2 /usr/share/man/man1/python2.1.gz
kono@Azure:~/ansible_pj$

なるほど。PATH は通っているけれど、$ python2.7 で呼び出した時は、 /usr/bin/python2.7 が呼び出され、$ /opt/ansible/bin/python2.7 では、そのとおりの pathPython2.7 が起動したわけですね。
結果、同じように import pexpect をしているけど、挙動が違うと。

では、 Ansible が参照する pippexpect をインストールしよう。

kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip install pexpect --user virtualenv
Can not perform a '--user' install. User site-packages are not visible in this virtualenv.
kono@Azure:~/ansible_pj$

ダメなようですね。
ちなみに、本当に参照している先が違うのでしょうか。

kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip show wheel
...
Location: /opt/ansible/lib/python2.7/site-packages
...
kono@Azure:~/ansible_pj$

これと

kono@Azure:~/ansible_pj$ pip2.7 show wheel
...
Location: /usr/lib/python2.7/dist-packages
...
kono@Azure:~/ansible_pj$

同じパッケージで目に入ったのが wheel なので指定させて頂いた。
まるで使う場所が違いますね。

別のアプローチを考えよう。
Ansible が利用するデフォルトの Python を指定するとか。

kono@Azure:~/ansible_pj$ pip2.7 list | wc -l
9
kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip list | wc -l
73
kono@Azure:~/ansible_pj$

この結果を見るとアプローチを変えるのは厳しそう。
/opt/ansible/lib/python2.7/site-packages 内に無理やり入れる方法を考えてみよう。

Azure にて、 /opt/ansible/lib/python2.7/site-package に何かを入れられるとは思いがたい。。。

なにせ、Azure Cloud Shell の制限事項として、 sudo がつかえないのである。

どこか詰んだ感じがしますね。
Ansible が使うパッケージの場所

kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip show wheel | grep Location
Location: /opt/ansible/lib/python2.7/site-packages
kono@Azure:~/ansible_pj$

ロケーションのディレクトリのパーミッション及び、所有者:グループ

kono@Azure:~/ansible_pj$ ls -l /opt/ansible/lib/python2.7/ | grep site-packages
-rw-r--r--  11 root root     0 Jun 15 19:04 no-global-site-packages.txt
drwxr-xr-x 120 root root  4096 Jun 18 20:26 site-packages
kono@Azure:~/ansible_pj$

root:root でないとインストールできないことがわかります。

試しに、 /opt/ansible/bin/pip install pexpect を実行

kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip install pexpect
Collecting pexpect
  Using cached https://files.pythonhosted.org/packages/89/e6/b5a1de8b0cc4e07ca1b305a4fcc3f9806025c1b651ea302646341222f88b/pexpect-4.6.0-py2.py3-none-any.whl
Collecting ptyprocess>=0.5 (from pexpect)
  Using cached https://files.pythonhosted.org/packages/d1/29/605c2cc68a9992d18dada28206eeada56ea4bd07a239669da41674648b6f/ptyprocess-0.6.0-py2.py3-none-any.whl
Installing collected packages: ptyprocess, pexpect
Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/opt/ansible/lib/python2.7/site-packages/ptyprocess-0.6.0.dist-info'
Consider using the `--user` option or check the permissions.

kono@Azure:~/ansible_pj$

--user をつけると

kono@Azure:~/ansible_pj$ /opt/ansible/bin/pip install pexpect --user
Can not perform a '--user' install. User site-packages are not visible in this virtualenv.
kono@Azure:~/ansible_pj$

Permission denied 権限がない。 sudo をつけると、、、

kono@Azure:~/ansible_pj$ sudo /opt/ansible/bin/pip install pexpect --user
bash: sudo: command not found
kono@Azure:~/ansible_pj$

コマンドがない。 orz

ということで、 expect モジュールですが、これは上手く出来た時に追記したいと思います。
非常に残念ですが、しょうが無いですね。

raw

raw - Executes a low-down and dirty SSH command — Ansible Documentation

純粋に ssh コマンドを実行して何かを手で実施する時と同じことを実施してくれるモジュール。

playbook

kono@Azure:~/ansible_pj$ cat raw.yaml
# Command modules test
- hosts: any
  user: takashi
  #become: true
  tasks:
    - name: tail syslog
      raw: tail /var/log/syslog
kono@Azure:~/ansible_pj$

ansible 実行

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts raw.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.67.49]

TASK [tail syslog] **************************************************************************************************************************************************************************************************************************
changed: [40.74.67.49]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.67.49                : ok=2    changed=1    unreachable=0    failed=0

kono@Azure:~/ansible_pj$

これではよくわからないので、 -vvv オプションをつけてみましょう。

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts raw.yaml -vvv
...json
TASK [tail syslog] **************************************************************************************************************************************************************************************************************************
task path: /home/kono/ansible_pj/raw.yaml:6
<40.74.67.49> ESTABLISH SSH CONNECTION FOR USER: takashi
<40.74.67.49> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'IdentityFile="/home/kono/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=takashi -o ConnectTimeout=10 -o ControlPath=/home/kono/.ansible/cp/8aa58877c0 -tt 40.74.67.49 'tail /var/log/syslog'
<40.74.67.49> (0, "Jun 24 01:36:11 test1 kernel: [   62.830553] hv_balloon: Data Size is 8\r\nJun 24 02:05:11 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10\r\nJun 24 02:05:14 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/uname -a removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:16 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -h removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:19 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -i removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:21 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/usr/bin/free removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:24 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/sbin/ip a removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:26 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/netstat -nlt removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:29 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=which python3 removes=None creates=None chdir=None stdin=None\r\nJun 24 02:12:17 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10\r\n", 'Shared connection to 40.74.67.49 closed.\r\n')
changed: [40.74.67.49] => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 40.74.67.49 closed.\r\n",
    "stdout": "Jun 24 01:36:11 test1 kernel: [   62.830553] hv_balloon: Data Size is 8\r\nJun 24 02:05:11 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10\r\nJun 24 02:05:14 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/uname -a removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:16 test1 ansible-command: Invoked with warn=True executable=None_uses_shell=False _raw_params=/bin/df -h removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:19 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -i removes=None creates=Nonechdir=None stdin=None\r\nJun 24 02:05:21 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/usr/bin/free removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:24 test1 ansible-command:Invoked with warn=True executable=None _uses_shell=False _raw_params=/sbin/ip a removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:26 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/netstat -nlt removes=None creates=None chdir=None stdin=None\r\nJun 24 02:05:29 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=which python3 removes=None creates=None chdir=None stdin=None\r\nJun 24 02:12:17 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10\r\n",
    "stdout_lines": [
        "Jun 24 01:36:11 test1 kernel: [   62.830553] hv_balloon: Data Size is 8",
        "Jun 24 02:05:11 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10",
        "Jun 24 02:05:14 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/uname -a removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:05:16 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -h removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:05:19 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -i removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:05:21 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/usr/bin/free removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:05:24 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/sbin/ip a removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:05:26 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/netstat -nlt removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:05:29 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=which python3 removes=None creates=None chdir=None stdin=None",
        "Jun 24 02:12:17 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10"
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.67.49                : ok=2    changed=1    unreachable=0    failed=0

kono@Azure:~/ansible_pj$

コマンドでは以下と同じことを行っています。

kono@Azure:~/ansible_pj$ ssh takashi@40.74.67.49 tail /var/log/syslog
Jun 24 02:05:14 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/uname -a removes=None creates=None chdir=None stdin=None
Jun 24 02:05:16 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -h removes=None creates=None chdir=None stdin=None
Jun 24 02:05:19 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/df -i removes=None creates=None chdir=None stdin=None
Jun 24 02:05:21 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/usr/bin/free removes=None creates=None chdir=None stdin=None
Jun 24 02:05:24 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/sbin/ip a removes=None creates=None chdir=None stdin=None
Jun 24 02:05:26 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=/bin/netstat -nlt removes=None creates=None chdir=None stdin=None
Jun 24 02:05:29 test1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=which python3 removes=None creates=None chdir=None stdin=None
Jun 24 02:12:17 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10
Jun 24 02:13:10 test1 ansible-setup: Invoked with filter=* gather_subset=['all'] fact_path=/etc/ansible/facts.d gather_timeout=10
Jun 24 02:17:01 test1 CRON[3938]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
kono@Azure:~/ansible_pj$

ソースコードは以下。ドキュメントしか無いことがわかります。

ansible/raw.py at devel · ansible/ansible · GitHub

ssh したあとのコマンドをしっかり記述することで、何でも出来そうですね。その反面べき等性は自分たちで実装する必要はあるのだと思います。

script

script - Runs a local script on a remote node after transferring it — Ansible Documentation

気になった特徴は以下の内容です。

This module does not require python on the remote system, much like the raw module.

つまり、 python の入っていないようなネットワークデバイスでもスクリプトが使えるということなんだと思います。

とはいえ、サンプルに Shell Script しか書かれていないので、心配になったため、Pythonスクリプトも準備する。

こんな感じで playbook を書いてみました。

kono@Azure:~/ansible_pj$ cat script.yaml
# Command modules test
- hosts: any
  user: takashi
  #become: true
  tasks:
    - name: execute local shell script
      script: ./scripts/get_cwd.sh
      register: result
    - debug:
        var: result
    - name: execute local python script
      script: ./scripts/get_cwd.py
      register: result
    - debug:
        var: result
kono@Azure:~/ansible_pj$

それぞれのスクリプトは以下の通り。

kono@Azure:~/ansible_pj$ cat ./scripts/get_cwd.sh
echo `pwd`
kono@Azure:~/ansible_pj$ cat ./scripts/get_cwd.py
#!/usr/bin/python3
# coding: utf-8
import os
print(os.getcwd())


kono@Azure:~/ansible_pj$

動かしてみましょう。

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts script.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.67.49]

TASK [execute local shell script] ***********************************************************************************************************************************************************************************************************
changed: [40.74.67.49]

TASK [debug] ********************************************************************************************************************************************************************************************************************************
ok: [40.74.67.49] => {
    "result": {
        "changed": true,
        "failed": false,
        "rc": 0,
        "stderr": "Shared connection to 40.74.67.49 closed.\r\n",
        "stdout": "/home/takashi\r\n",
        "stdout_lines": [
            "/home/takashi"
        ]
    }
}

TASK [execute local python script] **********************************************************************************************************************************************************************************************************
changed: [40.74.67.49]

TASK [debug] ********************************************************************************************************************************************************************************************************************************
ok: [40.74.67.49] => {
    "result": {
        "changed": true,
        "failed": false,
        "rc": 0,
        "stderr": "Shared connection to 40.74.67.49 closed.\r\n",
        "stdout": "/home/takashi\r\n",
        "stdout_lines": [
            "/home/takashi"
        ]
    }
}

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.67.49                : ok=5    changed=2    unreachable=0    failed=0

kono@Azure:~/ansible_pj$

どちらでも実行できましたね。
しかも、ローカルホストで作成しておいた Script ファイルをリモートで実行してくれている。
raw に似ていますね。

どうやって実現しているのか謎ですが、以外に便利な反面、冪等性の担保が難しそうです。
show run 取るくらいならこんな感じでいいかもしれませんけどね。

ソースコードは以下のリンクです。こちらも raw 同様、何もしていませんね。。。

ansible/script.py at devel · ansible/ansible · GitHub

shell

shell - Execute commands in nodes. — Ansible Documentation

次は、 shell モジュールですね。
ドキュメントの中にもあるように、 command モジュールライクらしいです。

The shell module takes the command name followed by a list of space-delimited arguments. It is almost exactly like the command module but runs the command through a shell (/bin/sh) on the remote node.

このドキュメントだけではちょっと良くわからなかったのでググってみた結果

shell モジュールは、 &, |, > 等のシェルの機能が使えるが、 command モジュールでは使えないというのが最も大きな差であるようだ。

ということで、 Playbook を書いてみた。

kono@Azure:~/ansible_pj$ cat shell.yaml
# Command modules test
- hosts: any
  user: takashi
  #become: true
  tasks:
    - name: Execute the command in remote shell.
      shell: ls /var/log/ | wc -l
      register: result
    - debug:
        var: result
kono@Azure:~/ansible_pj$

パイプでつなげているが、使えるだろうか。

kono@Azure:~/ansible_pj$ ansible-playbook -i hosts shell.yaml

PLAY [any] **********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
ok: [40.74.67.49]

TASK [Execute the command in remote shell.] *************************************************************************************************************************************************************************************************
changed: [40.74.67.49]

TASK [debug] ********************************************************************************************************************************************************************************************************************************
ok: [40.74.67.49] => {
    "result": {
        "changed": true,
        "cmd": "ls /var/log/ | wc -l",
        "delta": "0:00:00.004307",
        "end": "2018-06-24 03:57:31.229757",
        "failed": false,
        "rc": 0,
        "start": "2018-06-24 03:57:31.225450",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "29",
        "stdout_lines": [
            "29"
        ]
    }
}

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
40.74.67.49                : ok=3    changed=1    unreachable=0    failed=0

kono@Azure:~/ansible_pj$ 

きちんと出来ましたね。さすがです。 raw モジュールとも似ているのでしょうかね。。。

ansible/shell.py at devel · ansible/ansible · GitHub

ソースコードを見ても、ドキュメントとサンプルしか無いような気が。。。

telnet

telnet - Executes a low-down and dirty telnet command — Ansible Documentation

rawssh ではなく telnet で実行するという理解で合っているはず。

1時間くらい ubuntutelnet 出来るように調べてみたけど、あまり進展がなかったので、このモジュールについては今後機会があれば追記するようにします。

最後に

今回はコマンドモジュールにフォーカスして使いかたを自分用の備忘録として書き留めました。
ここまで読んで力になれ無かったとしても。。。ごめんなさい。
というか、未来の自分にごめんなさいをしたい。。。意外と expect を一番試してみたかったんですよね。そのため、結構試行錯誤したのですが、残念でした。

今度時間と環境を作ってリトライしようと思います。

以上です。

jinja2 備忘録

jinja2 の簡単な使いかたについての備忘録

jinja2 について調べてみたのはいいが、使えなくならないために備忘録として残す。

いきなりサンプル

Code
ファイル名: jinja2_sample.py

# coding: utf-8
from jinja2 import Template, Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('sample.tpl')

data = {'name': 'Kuro', 'lang': 'Python'}
disp = template.render(data)
print(disp)

Template file
ファイル名: sample.tpl

My name is {{ name }}. I like {{ lang }}.
{% set text=name %}
{{ text }}
{{ text }}
{{ text }}
{{ text }}
{{ text }}

2つのファイルを作ったので実行してみる

データは辞書にして渡す必要がるようです。
テンプレートファイルに set を入れるとテンプレートファイル内で変数として扱えるようです。便利。

実行結果

$ python3 jinja2_sample.py
My name is Kuro. I like Python.

Kuro
Kuro
Kuro
Kuro
Kuro

今のところ、テンプレートファイルのファイル名をコードに埋め込んでいるので、外だししたほうが良さそう。

まぁ、手順書を作るんならこの辺を使えればだいたいいい気がする。

以上

How to use argparse module on Python3

Learning using argparse module on Python3

Make an argparse.py file

At first, make a file that name is argparse.py file by any text editor.

Open the official document on your browser

Aliases
Japanese

Argparse チュートリアル — Python 3.6.5 ドキュメント

English

Argparse Tutorial — Python 3.6.5 documentation

Make the most simple script

Code is bellow.

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

Show help.

$ python3 argparse.py -h
usage: argparse.py [-h]

optional arguments:
  -h, --help  show this help message and exit
$

Add positional arguments

Make positional arguments.
Code

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
# Positional arguments.
parser.add_argument("echo")
args = parser.parse_args()
print(args)

Show help message.

$ python3 argparse.py -h
usage: argparse.py [-h] echo

positional arguments:
  echo

optional arguments:
  -h, --help  show this help message and exit

$

Run the script with foo in positional arguments.

$ python3 argparse.py foo
Namespace(echo='foo')
$

Check what functions in ArgumentParser()

Check in interpreter mode.

$ ipython
Python 3.6.4 (default, Jan  6 2018, 11:51:15) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import argparse

In [2]: parser = argparse.ArgumentParser()

In [3]: dir(parser)
Out[3]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_action_groups',
 '_actions',
 '_add_action',
 '_add_container_actions',
 '_check_conflict',
 '_check_value',
 '_defaults',
 '_get_args',
 '_get_formatter',
 '_get_handler',
 '_get_kwargs',
 '_get_nargs_pattern',
 '_get_option_tuples',
 '_get_optional_actions',
 '_get_optional_kwargs',
 '_get_positional_actions',
 '_get_positional_kwargs',
 '_get_value',
 '_get_values',
 '_handle_conflict_error',
 '_handle_conflict_resolve',
 '_has_negative_number_optionals',
 '_match_argument',
 '_match_arguments_partial',
 '_mutually_exclusive_groups',
 '_negative_number_matcher',
 '_option_string_actions',
 '_optionals',
 '_parse_known_args',
 '_parse_optional',
 '_pop_action_class',
 '_positionals',
 '_print_message',
 '_read_args_from_files',
 '_registries',
 '_registry_get',
 '_remove_action',
 '_subparsers',
 'add_argument',
 'add_argument_group',
 'add_help',
 'add_mutually_exclusive_group',
 'add_subparsers',
 'allow_abbrev',
 'argument_default',
 'conflict_handler',
 'convert_arg_line_to_args',
 'description',
 'epilog',
 'error',
 'exit',
 'format_help',
 'format_usage',
 'formatter_class',
 'fromfile_prefix_chars',
 'get_default',
 'parse_args',
 'parse_known_args',
 'prefix_chars',
 'print_help',
 'print_usage',
 'prog',
 'register',
 'set_defaults',
 'usage']

In [4]: 

We can see a lot of functions.
And there is add_argument function.
There is add_argument() method document.

Japanese

16.4. argparse — コマンドラインオプション、引数、サブコマンドのパーサー — Python 3.6.5 ドキュメント

Engelish

16.4. argparse — Parser for command-line options, arguments and sub-commands — Python 3.6.5 documentation

Add help detail message.

Code changes...

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
# Positional arguments.
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print(args)

Only add help= option.

Run this.

$ python3 argparse.py -h
usage: argparse.py [-h] echo

positional arguments:
  echo        echo the string you use here

optional arguments:
  -h, --help  show this help message and exit
$

Added echo argument message. OK, we can add posisional argument message!

Add argument type in positional argument.

Code is bellow.

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
# Positional arguments.
parser.add_argument("echo_num", help="echo the number you use here", type=int)
args = parser.parse_args()
print(args)

Run this help.

$ python3 argparse.py -h
usage: argparse.py [-h] echo_num

positional arguments:
  echo_num    echo the number you use here

optional arguments:
  -h, --help  show this help message and exit
$

OK, it seems good.

Run the script with 2 that is positional argument.

$ python3 argparse.py 2
Namespace(echo_num=2)

$

OK, next. I will give test string to this script.

$ python3 argparse.py test
argparse.py: error: argument echo_num: invalid int value: 'test'

shell returned 2

$

I got an error with helpfull message. It's good behavior.

Use optional arguments.

Make optional argument sample.

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
# Optional arguments
parser.add_argument("--verbose", help="increase output verbosity")
args = parser.parse_args()
if args.verbose:
    print("verbosity turned on")

parser.add_argument() is same.
It is EASY!

Run the script.

$ python3 argparse.py -h
usage: argparse.py [-h] [--verbose VERBOSE]

optional arguments:
  -h, --help         show this help message and exit
  --verbose VERBOSE  increase output verbosity

Run the script with optional argument.

$ python3 argparse.py --verbose 1
verbosity turned on

args.verbose becomes True, run the print function.
It seems good!

Customize!

Change to get True or False on --verbose option. Now, --verbose opiton is able to get integer values.
Code bellow.

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
# Optional arguments
parser.add_argument("--verbose", help="increase output verbosity", action="store_true")
args = parser.parse_args()
if args.verbose:
    print("verbosity turned on")

Run the script with -h.

$ python3 argparse.py -h
usage: argparse.py [-h] [--verbose]

optional arguments:
  -h, --help  show this help message and exit
  --verbose   increase output verbosity

Help text has changed.

Short options

Easy

# coding: utf-8
import argparse
parser = argparse.ArgumentParser()
# Optional arguments
parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
args = parser.parse_args()
if args.verbose:
    print("verbosity turned on")

Only add "-v" option. It's so easy!

Run the script with -h option.

$ python3 argparse.py -h
usage: argparse.py [-h] [-v]

optional arguments:
  -h, --help     show this help message and exit
  -v, --verbose  increase output verbosity

Help message has changed!

Thank you!

Python3 で Requests モジュール使い方の備忘録

Requests モジュールの備忘録

備忘録を書くことで、自分自身が使い方を忘れた時にそれを思い出す手助けとする。

Requests とは

Web アクセスののための Python モジュール?だと思います。
そもそも作られた理由が、urllib2 という Python 付属のモジュールがややこしすぎたからだとか。

Requests の公式ページにかかれているのは以下の通り。

Requests is an elegant and simple HTTP library for Python, built for human beings.

私の拙い訳ですと、

Requests は Python のためのエレガントでシンプルな HTTP ライブラリで、人間のために作られました。

うーん。変ですね。
translate.google.co.jp さんに翻訳していただきましょう。

Requestsは、人間のために構築された、Python用のエレガントでシンプルなHTTPライブラリです。

わかりやすい!

半端な翻訳よりよっぽどいいですね!テクノロジー。すごいです。

公式ページは以下からたどれます。
英語版

Requests: HTTP for Humans — Requests 2.18.4 documentation

日本語版

Requests: 人間のためのHTTP — requests-docs-ja 1.0.4 documentation

日本語版は、リリースバージョンが v1.0.4 と少し古い? 英語版だと v2.18.4 ですのでやはり古く感じてしまいますね。

更新履歴があるところを見つけました。良かったです。

Community Updates — Requests 2.18.4 documentation

インストール

$ pip install requests

で入るはずです。
入らなければ、公式を見ましょう。

Installation of Requests — Requests 2.18.4 documentation

Getting Started

ここにも書いてあるので、それでもいいと思います。

http://docs.python-requests.org/en/master/user/quickstart/#quickstart

やり方はそれぞれだと思いますが、やはり、インタプリタで試してからテキストファイルに落とすほうが確実だと思います。
今回はインタプリタで実行していきます。  

>>> import requests
>>> target_url = "https://github.com"
>>> r = requests.get(target_url)
>>> r.status_code
200

とりあえず、アクセスが出来ました。
この時拾ってきたレスポンスボディを表示させてみましょう。

>>> r.text
'\n\n\n\n\n\n<!DOCTYPE html>\n<html lang="en">\n  <head>\n    <meta charset="utf-8">\n  <link rel="dns-prefetch" href="https://assets-cdn.github.com">\n  <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com">\n  <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com">\n  <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com">\n  <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com">\n  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">\n  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">\n\n\n\n 
...

ちゃんと取ってこれているようです。整形されていないので、見づらいですね。
そういう問のために、BeautifulSoup4 という素敵なものもあるんですが、それはまた別途使ってみようと思います。

ちなみにこの時の r が持つメソッド一覧

>>> [print(x) for x in dir(r)]
__attrs__
__bool__
__class__
__delattr__
__dict__
__dir__
__doc__
__enter__
__eq__
__exit__
__format__
__ge__
__getattribute__
__getstate__
__gt__
__hash__
__init__
__init_subclass__
__iter__
__le__
__lt__
__module__
__ne__
__new__
__nonzero__
__reduce__
__reduce_ex__
__repr__
__setattr__
__setstate__
__sizeof__
__str__
__subclasshook__
__weakref__
_content
_content_consumed
_next
apparent_encoding
close
connection
content
cookies
elapsed
encoding
headers
history
is_permanent_redirect
is_redirect
iter_content
iter_lines
json
links
next
ok
raise_for_status
raw
reason
request
status_code
text
url
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
>>> 

この辺の詳しいことは、以下の リンク にも書いてあります。

Developer Interface — Requests 2.18.4 documentation

どんな値を拾ってデバッグしたいかによって、使いたいメソッド?が変わると思いますので、適宜ドキュメントを活用しましょう。
たとえば、ヘッダー情報を見てみたいときは、headers だったり、 request.headers を使えばわかります。

Requests は色々できて、ログインしてセッション維持して次のページへ遷移するとか、フォームに値を入れるとか、ユーザーエージェント情報を偽装?するとか。

そのあたりも順次追記していきたいと思います。


とりあえず、今日はここまで。(内容薄いな)
また、このページに追記します。

hbstudy#82 に遅刻参加してきました

hbstudy#82 とは

詳しくは下記リンクより。

hbstudy.connpass.com

このエントリについて

正直短くなります。
途中参加だったこともあり、全てを聞け無かったこと。各種技術について知らないことも多かったので、まずは備忘録まで。

k8s, Rancher の話について

私が聞けたのは最後のこの発表だけだった。開発に至る経緯からモニタリングまでのお話を聞くことが出来た。

Ranche 導入のきっかけ

Docker を導入したら、あまりにもコンテナが乱立した > 統合管理環境が欲しかった > Rancher 導入へ

Docker on Docker について

Docker on Docker を導入しているとのこと。
メリット * コンソールやSSHなどが分離されている。アプリケーションの動いているコンテナがお亡くなりなってもコンソールはとれる デメリット * 特に言及は無かった

Docker on Docker と言う使い方を考えたことも無かったので新しい刺激になってうれしかった。

管理系(サービスとして表に出ているサーバを管理するサーバ)について

これに使われているサービスも Docker を使っている。と言う事は、Rancher も使っている。とのこと。

Docker & Rancher すごい!

オンプレミスの強み

Blue, Green デプロイや Immutable Infrastructure なんかを実施するとき、1世代前のコンテナを時期リリースまでおなかの中で抱えておく事が出来る。その為のリソースはちゃんと確保している。その為切り戻しが一瞬で出来るようになっている。
AWSなどで実施しようとするといくら請求が来るか恐ろしい。

ShellScript 乱立

数えた結果100以上のShellScriptが出来上がったらしい。その辺をそのままにしておくと秘伝のたれになりかねないので、envsubstを使って共通化を謀ったらしい。

通化はいいことですね。

データについて

結局データの永続化は外部に出していた。

今はまだそうならざるを得ないのだなと感じた。Docker でデータの永続化が出来る時代はもう少し先???

DevOps な話について

出てきた。具体的な話は忘れたが、開発者も運用に入るようにしていた様だ。

SRE について

話が出てこなかったように思う。
個人的には SRE 大全 とあったのでもう少しシステムから離れた話が聞けるのではと思っていた。

会社内で Vision を定義して、それに沿って SREDevOps を定義していく必要がある。と個人的に解釈した。

Vision 大事!

サービスが大きくなりすぎて結局運用部隊を分けたくならないかについて

その為のマイクロサービスです。

なるほど。

一つの公開しているサービスを持っているチームがあって、それがスケールするとサービス内のマイクロサービスが大きくなってしまい、結局運用分離が発生するのでは無いかについては聞くことが出来無かった。

総じて

サービスのシステムや技術の話はすごく面白かった。ただ、個人的には SRE の SLI やエラーバジェットとってるとかその辺の事をもう少し突っ込んで聞きたかった。

以上。

NetOpsCoding#5 Mini Report

NetOpsCoding Report

I went to NetOpsCoding#5 in Japan at 10th of October in 2017.

スポンサー

Food: Cisco Drink: CTC America

自動化と監視の推進奮闘記

Presented by 安藤格也(ヤフー株式会社)

自動化

自動化はどこでも課題になっているようだ
古い機器も扱っているのでAPIが無いなど問題もある

マルチベンダーを利用している > 抽象化 > 自動化 で取り組んだ

Python からNW_Library があり、それを利用

NETCONF でとれるデータ != 構造化されたデータ

CLI で抽象化を試すことに

OSSを利用することで、コマンドでのOSの意識を消す事も抽象化により可能になった

CLI の結果を解析するライブラリ
google/textfsm 便利らしい

今回は、設定の自動化は fabric(python) でオペレーションを関数化したようだ

結果として、抽象化はうまく出来た用でした

Q & A

  1. CLI ベースで抽象化しているので、OSのバージョンアップにどう対応しているのか?
  2. ユニットテストをしっかり作ったので、OSのバージョンアップに追従出来るようになっている

  3. Ansible ではないのはなぜ?

  4. 用件を定義する中で、Ansible は駄目だと出てきた。(詳しい話は忘れた) (CLIベースで抽象化すると決まったのに、API経由しか無かったりなど)

  5. 誰がメンテするんですか問題

  6. 勉強会とドキュメント

監視

  • Prometheus

prometheus.io

  • Alertmanager

github.com

  • Grafana

github.com

Prometheus は集約できる
拠点ごとに置いた Prometheus を中央の Prometheus に集約するなど

Ansible x NAPALM x NSO 解説・比較パネルディスカッション

運用自動化ツールが続々リリース
これは!
ネットワーク運用変革時代!!!

横地 晃(株式会社エーピーコミュニケーションズ)

  • NAPALM は Python のライブラリ
  • Ansible 構成管理ツール

Ansible

モジュールの対応状況がベンダーやOSによってまちまち

簡単な Ansible でのネットワーク設定などの紹介

Ansible 2.4 新モジュールから抽象化するような機能が出てきた
- net_* モジュール

NAPALM

多機能で暑い抽象化 Python ライブラリ

github.com

情報取得メソッドはよく見ておこう。バージョンが上がるときに変わることが多々ある

NAPALM は show コマンドの結果を parse してくれる

NAPALM は Validate 機能がある
たとえば、YAML で Traceroute の path を定義しておいて、その通りになるかどうかテストできる

岩本 彰 (Cisco Systems)

TAC です。値段聞かれても答えれませんw

Network Service Orchestrator
略して、NSO
全てのコンフィグはモデルベース

果たして、古い IOS でも NSO は対応しているのだろうか

NSO は、CDB に設定情報を突っ込んでいる。それを、Yang ベースにNEDがデバイス用の設定をつくって、実機に反映させる流れ。その為、設定情報がすでにCDBに存在していればデバイスに対して何もしない

ディスカッション

記事から削除

最後に

公開が遅れてしまったこと、大変後悔している。個人的な重いとしては勉強会なりセミナーなりが終わった次の日にはアップしていたいのだが、今回は出来なかった。今更ながらでは在るが、個人的備忘録として公開させて頂く。

Python3 で正規表現を使ったときのメモ

目的

Python3 で正規表現を使うときの備忘録とする

環境

  • Jupyter Notebook
  • Python3.6

参考

Python3.6 の公式ドキュメント
6.2. re — 正規表現操作 — Python 3.6.3 ドキュメント

ciscoconfparse

github.com

続きを読む