Ansibleのcopyモジュールはどうやって冪等性を担保しているのか
この
前書き
今年の
このyum
モジュールで
「何であろうと
と
この
Q: サーバー内での
ファイルコピーとか どうしてるんでしょう? (意訳) A: ローカルで
ファイルを 保持して、 copy
モジュールとか使います(意訳)
と
そこでyum
ではcopy
では
copyとyumを見比べる
ソースを
項目 |
yum |
copy |
---|---|---|
何を
|
yumコマンドを
|
ローカルから
|
Changed条件
|
パッケージの
or
パッケージを
|
ファイルの
or
ファイルを
|
やって
|
* インストール状態の
* 必要に
|
*
* 必要に
|
※ yum
に
気にcopy
モジュールの
yum
と
stat
コマンドを使っても、 ファイルサイズまでしかわからない cp
コマンドの挙動的に、 inodeは
変化しない ファイルの
内容に かかわらず Changedは 変化する ファイルの
内容変化は わからない
copy
モジュールにはbackup
パラメーターが存在する
と
$ date > test.txt && cp test.txt var && stat var/test.txt
File: var/test.txt
Size: 32 Blocks: 8 IO Block: 4096 regular file
Device: 10305h/66309d Inode: 446998103 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ attakei) Gid: ( 985/ users)
Access: 2019-12-08 23:39:01.628030154 +0900
Modify: 2019-12-08 23:42:18.812931334 +0900
Change: 2019-12-08 23:42:18.812931334 +0900
Birth: 2019-12-08 23:39:01.628030154 +0900
$ date > test.txt && cp test.txt var && stat var/test.txt
File: var/test.txt
Size: 32 Blocks: 8 IO Block: 4096 regular file
Device: 10305h/66309d Inode: 446998103 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ attakei) Gid: ( 985/ users)
Access: 2019-12-08 23:39:01.628030154 +0900
Modify: 2019-12-08 23:42:25.529653015 +0900
Change: 2019-12-08 23:42:25.529653015 +0900
Birth: 2019-12-08 23:39:01.628030154 +0900
$ date >> test.txt && cp test.txt var && stat var/test.txt
File: var/test.txt
Size: 64 Blocks: 8 IO Block: 4096 regular file
Device: 10305h/66309d Inode: 446998103 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ attakei) Gid: ( 985/ users)
Access: 2019-12-08 23:39:01.628030154 +0900
Modify: 2019-12-08 23:42:31.103031998 +0900
Change: 2019-12-08 23:42:31.103031998 +0900
Birth: 2019-12-08 23:39:01.628030154 +0900
$ rm test.txt
$ date > test.txt && cp test.txt var && stat var/test.txt
File: var/test.txt
Size: 32 Blocks: 8 IO Block: 4096 regular file
Device: 10305h/66309d Inode: 446998103 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ attakei) Gid: ( 985/ users)
Access: 2019-12-08 23:42:34.633060910 +0900
Modify: 2019-12-08 23:43:51.577024235 +0900
Change: 2019-12-08 23:43:51.577024235 +0900
Birth: 2019-12-08 23:39:01.628030154 +0900
実際に調べてみる
とv2.9.2
で
まずはmain()から
Ansibleモジュールのmain()
を__name__ == '__main__'
でmain()
関数を
チェックサムを調べている
550 checksum_dest = None
551
552 if os.path.isfile(src):
553 checksum_src = module.sha1(src)
554 else:
555 checksum_src = None
556
557 # Backwards compat only. This will be None in FIPS mode
558 try:
559 if os.path.isfile(src):
560 md5sum_src = module.md5(src)
561 else:
562 md5sum_src = None
563 except ValueError:
564 md5sum_src = None
引数のchecksum_src
に
604 if os.path.exists(b_dest):
605 if os.path.islink(b_dest) and follow:
606 b_dest = os.path.realpath(b_dest)
607 dest = to_native(b_dest, errors='surrogate_or_strict')
608 if not force:
609 module.exit_json(msg="file already exists", src=src, dest=dest, changed=False)
610 if os.access(b_dest, os.R_OK) and os.path.isfile(b_dest):
611 checksum_dest = module.sha1(dest)
更にchecksum_dest
に
チェックサムを比較している
if checksum_src != checksum_dest or os.path.islink(b_dest):
if not module.check_mode:
# 状況に応じた様々な処理
try:
if backup:
pass
except (IOError, OSError):
module.fail_json(msg="failed to copy: %s to %s" % (src, dest), traceback=traceback.format_exc())
changed = True
else:
changed = False
終盤にchecksum_dest
とchecksum_src
のelse
のchanged = False
と
フォルダごとの転送でも頑張る
チェックサムのos.path.isfile
がTrue
のsrc
, dest
どちらもがNone
に
ただし、remote_src=yes
のcopy_diff_files()
関数を
399def copy_diff_files(src, dest, module):
400 changed = False
401 owner = module.params['owner']
402 group = module.params['group']
403 local_follow = module.params['local_follow']
404 diff_files = filecmp.dircmp(src, dest).diff_files
405 if len(diff_files):
406 changed = True
407 if not module.check_mode:
408 for item in diff_files:
409 src_item_path = os.path.join(src, item)
関数内にて
filecmp.dircmp(src, dest).diff_files
がchanged = True
とchanged = False
で
結論
copy
モジュールは、
ローカルtoリモートでの
ファイルコピー時には、 sha1
でのチェックサムを 比較して 上書き要否を 判定する リモート上でのファイルコピー時には、
filecmp
モジュールを利用して 上書き要否を 判定する
とyum
モジュールよりは
余談
ちなみに、lizard
で
% lizard
================================================
NLOC CCN token PARAM length location
------------------------------------------------
2 1 12 2 2 __init__@285-286@./ansible-copy-module.py
7 3 87 1 8 clear_facls@293-300@./ansible-copy-module.py
13 4 100 1 16 split_pre_existing_dir@303-318@./ansible-copy-module.py
7 2 66 5 11 adjust_recursive_directory_permissions@321-331@./ansible-copy-module.py
61 37 544 2 63 chown_recursive@334-396@./ansible-copy-module.py
25 8 189 3 26 copy_diff_files@399-424@./ansible-copy-module.py
40 24 403 3 47 copy_left_only@427-473@./ansible-copy-module.py
14 5 133 3 16 copy_common_dirs@476-491@./ansible-copy-module.py
225 95 2067 0 293 main@494-786@./ansible-copy-module.py
4 1 28 2 18 __init__@376-393@./ansible-yum-module.py
18 7 122 2 19 _enablerepos_with_error_checking@395-413@./ansible-yum-module.py
28 8 179 1 41 is_lockfile_pid_valid@415-455@./ansible-yum-module.py
24 8 179 1 28 yum_base@457-484@./ansible-yum-module.py
4 2 43 2 5 po_to_envra@486-490@./ansible-yum-module.py
17 9 144 2 23 is_group_env_installed@492-514@./ansible-yum-module.py
45 23 426 5 55 is_installed@516-570@./ansible-yum-module.py
28 9 238 4 36 is_available@572-607@./ansible-yum-module.py
31 11 276 4 41 is_update@609-649@./ansible-yum-module.py
45 13 386 4 57 what_provides@651-707@./ansible-yum-module.py
18 9 124 2 36 transaction_exists@709-744@./ansible-yum-module.py
17 4 103 2 20 local_envra@746-765@./ansible-yum-module.py
36 15 285 1 40 set_env_proxy@768-807@./ansible-yum-module.py
19 3 104 2 22 pkg_to_dict@809-830@./ansible-yum-module.py
7 4 66 3 7 repolist@832-838@./ansible-yum-module.py
25 20 310 3 32 list_stuff@840-871@./ansible-yum-module.py
27 13 260 5 45 exec_install@873-917@./ansible-yum-module.py
110 41 828 3 172 install@919-1090@./ansible-yum-module.py
44 13 306 3 66 remove@1092-1157@./ansible-yum-module.py
3 1 31 1 4 run_check_update@1159-1162@./ansible-yum-module.py
18 6 195 1 45 parse_check_update@1165-1209@./ansible-yum-module.py
156 48 1129 3 203 latest@1211-1413@./ansible-yum-module.py
99 33 604 2 120 ensure@1415-1534@./ansible-yum-module.py
2 1 6 0 2 has_yum@1537-1538@./ansible-yum-module.py
72 24 507 1 102 run@1540-1641@./ansible-yum-module.py
7 1 48 0 20 main@1644-1663@./ansible-yum-module.py
2 file analyzed.
==============================================================
NLOC Avg.NLOC AvgCCN Avg.token function_cnt file
--------------------------------------------------------------
662 43.8 19.9 400.1 9 ./ansible-copy-module.py
1262 34.8 12.6 266.4 26 ./ansible-yum-module.py
こんなcopy
モジュールの
意外なことに、
copy
のほうが 行数が 少ない CNN(複雑度)は、
copy
のほうが 高い yum
は処理を 細かく 散らしているに 対して、 copy
は少数に 加えて main
がやばめ
と
※脚注