ansible-vaultで作ったpasswordに改行が入るときの対応
ansible-vaultでパスワードを暗号化してセットしたつもりで展開されたら改行が入ってしまっていて、
以下のようなことになっていることがあります。
mysql_endpoint = mysql+pymysql://USER:PASSWORD @HOSTNAME:3306/database
@から改行されてしまって、確認しようとしたらmysqlへの接続エラーみたいな...
そう言った時大体、
echo 'password' | ansible-vault encrypt
とやってしまっていますが、
echo -n 'password' | ansible-vault encrypt
を入れると改行を取り除いてくれますね。
echo の -n
オプションは、man echo を読んでいただけるとわかると思いますが、
-n do not output the trailing newline
と書かれてて、改行を出力しないようにしてくれます。
よく忘れて、ansible実行すると大体これにハマるので注意したいです。
json.dumpsした値が期待した通りか確認するunittest
python3.7以前の辞書(dict)とJSONオブジェクトは順序立てられてません。
今回はだいぶ古いpythonなため、順序立てられていませんでした。
そのため、dictをjson.dumpsしたりすると、順番が崩れたりします。
オプションとして、 json.dumps(dict, sort_keys=True)
のような
sort_keysを付けられるようなオプションが存在しています。
今回自分がハマったのはunittest引数として、json.dumpsがセットされたときにその順序をどう検証するのか?
というところで少し手間取ったので、まとめていこうと思います。
m_put.assert_called_once_with(data=json_string, headers=headers)
と、いうメソッドが正しい引数で呼ばれているかの確認ですね。
unittestがなく怖かったのですが、元のコードの挙動が正確にわからないため、
元のコードは極力いじりたくないという思いもありました。
当然コードの方には、その直前に json_string = json.dumps(raw_data)
のようなことが書かれています。
call = m_put.call_args call_args, call_kwargs = call self.assertEqual(json.loads(call_kwargs['data']), json_string) self.assertEqual(call_kwargs['headers'], headers)
のように、call_argsで引数を取得し、
jsonの部分は json.loads()
して比較することで、問題ないことを確認しました。
無意識に頭の中でdataの中身がdictと考えてしまい、無駄に時間すごしたし、ランダムに変わってしまう値にどうすべきか、
時間を使ってしまいましたが、 callで取れるという学びがありました。
これで、json.dumps()
するときに sort_keys しても大丈夫な確認もとれました。

- 作者:Brian Okken
- 発売日: 2018/08/29
- メディア: 単行本(ソフトカバー)
keyやクラス変数の確認
pythonにて、dictに特定のkeyあるかなーとか、クラス変数に期待した変数はあるかなーという確認する方法をたまに忘れるからメモです。
dict型
>>> dict = {'ptyhon_key': 'python_value', 'ruby_key': 'ruby_value'} >>> if 'java_key' in dict: ... print(dict['java_key']) ... >>> if 'ruby_key' in dict: ... print(dict['ruby_key']) ... ruby_value
クラス変数
>>> class Valiable(object): ... def __init__(self): ... self.python_key = 'python_value' ... self.ruby_key = 'ruby_value' ... >>> val = Valiable() >>> if hasattr(val, 'ruby_key'): ... print(val.ruby_key) ... ruby_value >>> if hasattr(val, 'java_key'): ... print(val.ruby_key) ... >>>
のように確認する。
Drone CIで Python-MySQLを使おうとしたら少しハマったのでその対応
今までunittestとかなかったpython2で動いてたスクリプトがあって、あまりにも変更するのが怖いからとりあえずテスト書いて、CIで動くと便利だよねーって思い DroneCIの設定を始めました。 まずはこんな感じかなとdrone.ymlを準備しました。
--- kind: pipeline name: Unit tests steps: - name: execute unit test image: python:2 commands: - pip install --upgrade pip - pip install MySQL-Python sqlparse pings paramiko cryptography mock - python -m unittest discover . when: event: [push, pull_request]
そのとき、MySQL-Pythonでこけました。以下のようななんかパッケージがたりてないようなエラーにはまりました。
Failed to build MySQL-Python 94 Installing collected packages: MySQL-Python, sqlparse, pings, ipaddress, pycparser, cffi, enum34, cryptography, pynacl, bcrypt, paramiko, funcsigs, mock 95 Running setup.py install for MySQL-Python: started 96 Running setup.py install for MySQL-Python: finished with status 'error' 97 ERROR: Command errored out with exit status 1: 98 command: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-MVeMp_/mysql-python/setup.py'"'"'; __file__='"'"'/tmp/pip-install-MVeMp_/mysql-python/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-avyllU/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python2.7/MySQL-Python 99 cwd: /tmp/pip-install-MVeMp_/mysql-python/ 100 Complete output (38 lines): 101 running install 102 running build 103 running build_py 104 creating build 105 creating build/lib.linux-x86_64-2.7 106 copying _mysql_exceptions.py -> build/lib.linux-x86_64-2.7 107 creating build/lib.linux-x86_64-2.7/MySQLdb 108 copying MySQLdb/__init__.py -> build/lib.linux-x86_64-2.7/MySQLdb 109 copying MySQLdb/converters.py -> build/lib.linux-x86_64-2.7/MySQLdb 110 copying MySQLdb/connections.py -> build/lib.linux-x86_64-2.7/MySQLdb 111 copying MySQLdb/cursors.py -> build/lib.linux-x86_64-2.7/MySQLdb 112 copying MySQLdb/release.py -> build/lib.linux-x86_64-2.7/MySQLdb 113 copying MySQLdb/times.py -> build/lib.linux-x86_64-2.7/MySQLdb 114 creating build/lib.linux-x86_64-2.7/MySQLdb/constants 115 copying MySQLdb/constants/__init__.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 116 copying MySQLdb/constants/CR.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 117 copying MySQLdb/constants/FIELD_TYPE.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 118 copying MySQLdb/constants/ER.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 119 copying MySQLdb/constants/FLAG.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 120 copying MySQLdb/constants/REFRESH.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 121 copying MySQLdb/constants/CLIENT.py -> build/lib.linux-x86_64-2.7/MySQLdb/constants 122 running build_ext 123 building '_mysql' extension 124 creating build/temp.linux-x86_64-2.7 125 gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -Dversion_info=(1,2,5,'final',1) -D__version__=1.2.5 -I/usr/include/mariadb -I/usr/include/mariadb/mysql -I/usr/local/include/python2.7 -c _mysql.c -o build/temp.linux-x86_64-2.7/_mysql.o 126 In file included from _mysql.c:44: 127 /usr/include/mariadb/my_config.h:3:2: warning: #warning This file should not be included by clients, include only <mysql.h> [-Wcpp] 128 #warning This file should not be included by clients, include only <mysql.h> 129 ^~~~~~~ 130 In file included from _mysql.c:46: 131 /usr/include/mariadb/mysql.h:444:3: warning: function declaration isn’t a prototype [-Wstrict-prototypes] 132 MYSQL_CLIENT_PLUGIN_HEADER 133 ^~~~~~~~~~~~~~~~~~~~~~~~~~ 134 _mysql.c: In function ‘_mysql_ConnectionObject_ping’: 135 _mysql.c:2005:41: error: ‘MYSQL’ {aka ‘struct st_mysql’} has no member named ‘reconnect’ 136 if ( reconnect != -1 ) self->connection.reconnect = reconnect; 137 ^ 138 error: command 'gcc' failed with exit status 1 139 ---------------------------------------- 140 ERROR: Command errored out with exit status 1: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-MVeMp_/mysql-python/setup.py'"'"'; __file__='"'"'/tmp/pip-install-MVeMp_/mysql-python/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-avyllU/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python2.7/MySQL-Python Check the logs for full command output.
普通に調べると、CentOSなら yum -y install python-devel mysql-devel gcc
をインストールする必要があるというのですが、dockerのpython:2のイメージでは、それは無理。
ということで、centos:centos7に変更して実行することにしました。
そして、centos:centos7のイメージでは python-pip
をインストールできないので、epel-releaseを事前にインストールする必要があります。
--- kind: pipeline name: Unit tests steps: - name: execute unit test image: centos:centos7 commands: - yum -y install python-devel mysql-devel gcc - yum -y install epel-release && yum clean all - yum -y install python2-pip - pip install --upgrade pip - pip install MySQL-Python sqlparse pings paramiko cryptography mock - python -m unittest discover . when: event: [push, pull_request]
早くpython3で動くように書き換えたいですね。その前にlintチェックも入れてこれもdroneでチェックできるようにする番だ。

継続的デリバリー 信頼できるソフトウエアリリースのためのビルド・テスト・デプロイメントの自動化 (アスキードワンゴ)
- 作者:Jez Humble,David Farley,和智 右桂,高木 正弘
- 発売日: 2017/08/09
- メディア: Kindle版
特定のIPだけ許可したい時の判定方法
プライベートクラウドを運用していると、当然 DNS as a Serviceなんかも提供することになるのですが、OpenStackでは、Designateが第一選択肢として上がると思います。
そして、プライベートクラウドで外部IPを登録されてしまっては困るので、そういった部分は制限したいという要望がでてきます。
また、社内システムなんかでも特定のIPレンジだけ許可したいということもあるでしょう。そういったときにどうすべきか考えなくてはいけなかったので、考えてみました。
pythonのipaddressというモジュールを使います。
ipaddress.ip_networkで、networkを出します。 WHITE_LISTに登録された、IPレンジ、IPアドレスを一つずつチェックしていきます。 20.20.20.20みたいIP アドレスを直に指定すると、 20.20.20.20/32とされます。
そして、そのレンジに対象のIPがマッチするかどうかチェックしていくと簡単にマッチするかどうか判定できます。
deny list等を作るとレンジが大きすぎるため、IPをどうにか制限したいと言う場合はallow listとした方が 管理も簡単になります。
スクリプト
#/usr/bin/env python # coding: utf-8 import ipaddress ALLOW_LIST = ['10.0.0.0/8', '192.168.0.0/16', '20.20.20.20'] def checker(ip): for wl in ALLOW_LIST: ip_nw = ipaddress.ip_network(wl) if ip in ip_nw: result = True break else: result = False return result if __name__ == "__main__": ip = ipaddress.ip_address('10.10.10.10') print('result: ', checker(ip)) ip = ipaddress.ip_address('1.10.10.10') print('result: ', checker(ip)) ip = ipaddress.ip_address('192.168.0.5') print('result: ', checker(ip)) ip = ipaddress.ip_address('20.20.20.20') print('result: ', checker(ip))
実行結果
$ python ip_checket.py result: True result: False result: True result: True

独学プログラマー Python言語の基本から仕事のやり方まで
- 作者:コーリー・アルソフ
- 発売日: 2018/02/24
- メディア: 単行本
「ジェームズ・クリアー式複利で伸びる1つの習慣」を読んで習慣の作り方を考える
今回読んだのは、「ジェームズ・クリアー式複利で伸びる1つの習慣」という本で、読むきっかけは知人がよかった言っていたからだ。
自分は、飽きやすい方だというのを自覚していて何かとやめがちで、習慣とか作る前に大体飽きるか他のことに興味をもってしまうかで長続きしにくい方なのかなと思っていました。
なので、今回自分にとって今まで何がいけなかったのかを考える良いきっかけになりました。
そして、コロナ禍で自分と向き合う良い機会で近年気づいててもなかなか出来ていなかったダイエットに挑戦しました。
その経験を踏まえ、紹介していければと思います。
まず初めに、 複利で伸びるとはどういうことかというと、人間毎日1%の習慣の改善をおこなっていくと、最初の1%は対したこないかもしれないが、1年間、毎日自分の習慣を1%よくする生活していけば、1年後に37倍になります。
そういった意味でも本書籍では習慣づけるためには習慣は小さいものから始めるとかいてあります。
自分のケースで話せば、最初に自分の習慣を変えたのは、朝寝起きに体重計に乗ることでした。
それまでは寝起きにスマートフォンでSNSを見たりダラダラしていましたが、その悪習慣を断ち、まず体重計にのることから始めました。
本書には最初の習慣に2分やることと書かれいますが、1分もかかりません。そして、乗ったらfitbitに体重と体脂肪率を記録する。それだけです。
毎日計測することで、一喜一憂もしますが、自分の体重が減ったか増えたか日々確認できます。0.1kgでも減った日はもちろん嬉しいしそれがうれしく、走るモチベーションにつながるし、増えた日は食事も気をつけようと気が引き締まりましたね。
ここで、本書に書かれていた習慣化に役立つtipsを紹介すると、
- 最初の習慣はなるべく小さく、本当に習慣化するための動機付けになることをする
- 2分だけやってみる
- 記録をつける
です。僕が本当にしたかったことは言うまでもなく、ダイエットをすることです。
そのために、走ろうと考えてました。
そして、2分だけやってみるのは、2分もかからない体重計にのること。
最後に記録をつけること。体重計に乗って記録をつけて推移を確認するので2分程度かもしれません。もっといえば、fitbitの体重計を買ってしまえば記録をつける必要もなくなり手間と感じる必要もないかもしれません。

Fitbit フィットビット スマート体重計 Aria2 WiFi/Bluetooth対応 White【日本正規品】 FB202WT-JP
- 発売日: 2019/06/04
- メディア: エレクトロニクス
そして、朝子供を見送ったら後、走りに行きます。
体重計にのったことで、嬉しい日は足取りも軽いし、増えた日は普段より負荷を高くするためにちょっと距離伸ばそうかな。とかスピード上げようかな。とか考えたりしました。
ここで、もう一つ習慣について紹介すると、
本書で触れられてたのですが、習慣には、良い習慣、悪い習慣、どっちでもない習慣と3つの習慣があります。悪い習慣は直すべき習慣で、どっちでもない習慣というものがあります。
例えば、「朝N時に起きる」とか「ご飯をたべる」とか悪くもよくもない習慣です。
新しい習慣を始めたいのならば、まずはそういった習慣の後につけるのが一番やりやすいと紹介されています。
ここまで2つのことをはじめましたが、どちらも特定の習慣の後です。
朝起きたら -> 体重計
子供を見送ったら -> 走りに行く
どちらも日常的にほぼ 必ずと言っていいほどある習慣です。もちろん、見送る必要がなくなったら、また変わってくると思いますが、しばらくはそのままです。
そして、毎朝走るわけですが、毎日できるわけではありません。何かしら予定が入ることもしばしあります。そういったときにやめないこと、それが大事です。出来る限り早く再開することをめざします。9月は雨も多かったです。雨の日は外に出れません。でも雨が止んでる日は走ります。時には時間を変えて走りました。
そして、8月から始めた習慣をベースにしたダイエットは74.7から始まり、10/14時点で70.8kgまで減らすことに成功しました。
まだまだこれからも続けて、68kgまで落とすのが目標ですが、それ以降もキープする必要があります。そういったときに、今回始めた 体重計に乗る習慣は自分にとって良い薬となるでしょう。
今回本を読んで挑戦し始めて2.5ヶ月ほどですが、習慣化できてきてるんじゃないかなーと思っているし、常にモチベーションを保てているのは本のおかげじゃないのかなと思うので、これからも小さい改善から大きい目標が達成できるよう習慣の見直していきたいですね。
まとめ
- 習慣は小さく始める
- 2分だけやってみる
- 記録をつける
- 良い習慣/どちらでもない習慣の直後に新しい習慣を取り入れる
- サボってもすぐに始める
今回ダイエットに関して意識した、習慣化するために本から学んで実践したことは上記5つのことになります。
もし興味を持たれた方がいましたが、まだまだ本書には色んなことが書かれているので、読んでみてください。
ひよこと学ぶ ITエンジニアのための インプット・アウトプット エッセンシャルガイド を読んで
ひよこと学ぶ ITエンジニアのための インプット・アウトプット エッセンシャルガイド
という本が出版されたので読んでみた。
仕事の中でまとめるドキュメントなども含めて、言語化したとにモヤッとすることがあったり、
ブログとかも途中で飽きてしまったりすることがある。
そういう時は決まってインプットがたりてなかったり、適当になったりしてるときなんだけど。
そういう時のための何かのヒントになればなと思い、ちょうどよく出版されたこの本を読むことにした。
インプットについて
この本では、まずインプットを次のような工程にわけている。
情報の入手 -> 咀嚼 -> 理解
情報の入手は、簡単に言えば書籍、web、ブログ、勉強会などで読んだり聞いたりして仕入れることを意味することだ。
ここは誰でも簡単に情報を入手していくことが可能だろう。
ただ、こういった情報の入手もなんとなくではなく、目的をもつことが大事だと書かれている。
あとは、自分にあったレベル、土台の知識の入手も必須なので注意したい。
なんとなく情報を入手してしまうと、咀嚼の段階でぼんやりしてしまう傾向が自分にはあると思う。
重要と思われることを箇条書きで章をまとめたり、絵に書いたり咀嚼できるようにするのが良いと書かれていたのでやっていこう。 また、技術的なことなら手を動かして挙動を確かめるとかでも良いのかもしれない。
上記のフェーズを経て理解に至るのだけど、ふんわり進めることが多い自分にとっては今後改善していくポイントが見えたかなと思う。
アウトプットについて
インプットした知識を使って形にすること、第三者へ理解出来るようにしていくこと。
本書には以下のようなメリットが書かれていたが、アウトプットするなかで一番大事なのは正しく理解できたかだと思ってるので、 アウトプットは大事にしたい。
- アウトプットのメリット
- インプットした内容が正しく理解できているか確認できる
- 他社からフィードバックを得ることができる
- アウトプットをする人は似たような人が集まりよりインプットがしやすい環境に近づける
- 会社/個人のプレゼンスの向上
最後に書かれていて一番響いたのが、達成可能な目標をたてること だ。
たしかに、毎日技術ブログ更新とかそういうところは確かに難しい、でもマイペースに続けられるようにしたい。
そしてこの本で、最近の自分のインプットの反省点が浮き彫りになったので、今後は咀嚼の段階でしっかり理解できるようなまとめ方をしよう。