読者です 読者をやめる 読者になる 読者になる

ようへいの日々精進XP

どげんもこげんも無かろうもん

小ネタ道場一本勝負 〜 MacOS X でランダムな英数字を生成する 〜

小ネタ道場一本勝負 MacOS X メモ

たのもう

MacOS X でランダムな英数字を生成したいんです。

もちろん、pwgen というコマンドがあるのは知っていますが、今回は pwgen は使わない方法を模索します。

技あり!を取られた気分

こんな感じで

cat /dev/urandom | tr -dc A-Za-z0-9 | fold -w32 | head -n1

いけるはず…

ところが…

$ cat /dev/urandom | tr -dc A-Za-z0-9 | fold -w32 | head -n1
tr: Illegal byte sequence

お…技ありを取られた気分。

なぜ、こんな事が起こるかについては、以下の記事に書かれていました。

unix.stackexchange.com

Computers store data as sequences of bytes. A text is a sequence of characters. There are several ways to encode characters as bytes, called character encodings. The de facto standard character encoding in most of the world, especially on OSX, is UTF-8, which is an encoding for the Unicode character set. There are only 256 possible bytes, but over a million possible Unicode characters, so most characters are encoded as multiple bytes. UTF-8 is a variable-length encoding: depending on the character, it can take from one to four bytes to encode a character. Some sequences of bytes do not represent any character in UTF-8. Therefore, there are sequences of bytes which are not valid UTF-8 text files.

tr is complaining because it encountered such a byte sequence. It expects to see a text file encoded in UTF-8, but it sees binary data which is not valid UTF-8.

cat /dev/urandomtr が期待しない文字列(UTF-8 では無い文字列)が流れてきているからとのことです。

ということで、一本

こんな感じで

$ export LC_ALL=C; cat /dev/urandom | tr -dc A-Za-z0-9 | fold -w32 | head -n1
2u8uJ3zweCwHAvRjTsIYUKjXGG9KId5y

有難うございました

unix.stackexchange.com

やっぱり、pwgen が良い気がしました。

2017 年 03 月 28 日(火)

日々

ジョギング

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

Markdown でスライドが書ける Deckset がなかなか良いのでメモ

Deckset メモ

さようなら Keynote さようなら PowerPoint

は言い過ぎかもしれないけど Markdown でスライドを書ける Deckset を使い始めました。

www.decksetapp.com

Deckset の何が良いとや?

  • 繰り返しになるが Markdown で書けるので、ざっと書いたメモがそのままスライドになる

これに限る。

凝ったアニメーションや装飾等は無く、テーマの数も少ないが、元々 KeynotePowerPoint でも使いこなせていなかったので、自分としてデメリットにならない。

また、プレゼンター用のノートも書けたりするので、カンペが必須な自分も心配 Nothing 。

書式等については、以下のドキュメントに纏められているので安心ですたい。

docs.decksetapp.com

要望的な何か

スライドのリモートコントロールKeynote Remote のように iOSバイスから手軽に出来ると嬉しいです。

github.com

github.com

一応、上記のようにオープンソースで公開されているものの、個人的には敷居が高いです…

ということで

初めての Deckset 作品

speakerdeck.com

今週、開催予定の Ansible徹底入門 輪読会 #0で発表する予定の資料です。

Deckset は

華美な装飾は不要、スライドの中身で勝負したい(笑)、Markdown が母国語になっているエンジニアの皆さんにお薦めだと思います。

2017 年 03 月 27 日(月)

日々

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

体や心にガタがきているようで、どうしたもんだか。

元気でいてくれることだけが願い。

2017 年 03 月 26 日(日)

日々

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

4LDK

内覧してきた。

リビングもだいぶん広くて、いい感じの部屋だった。

「Ansible 徹底入門」を読んでる途中だけど Ansible Callback Plugin(CloudWatch Logs にイベントを送信するプラグイン) を作ってみたのメモ

Ansible python CloudWatch Logs

Ansible 徹底入門

www.shoeisha.co.jp

自分自身はまだ読んでいる途中ですが、Ansible をこれから利用しようと考えている方から、各種クラウド環境と組み合わせた一歩踏み込んだ利用を考えて方まで幅広い層の皆さんにお薦め出来ると思います。

燃えてキタ━━━━(゚∀゚)━━━━!!

Ansible 徹底入門を読み進めているうちに、燃えてきたので Ansible Callback Plugin(CloudWatch Logs にイベントを送信するプラグイン) を作ってみました。

Ansible Plugin について

以下の資料にまとめました。

speakerdeck.com

作った Ansible Plugin

github.com

Playbook の実行結果等を CloudWatch Logs に転送するやつです。

プラグインを実装するにあたり、logstash プラグインの実装を参考にさせて頂きました。ありがとうございます。

デモ

デモ環境

$ python --version
Python 2.7.13

$ ansible --version
ansible 2.2.1.0
  config file = /path/to/.ansible.cfg
  configured module search path = Default w/o overrides

プラグインの置き場

ansible.cfg で指定します。

[default]
callback_plugins = ~/path/to/plugins
callback_whitelist = cloudwatch_logs

callback_plugins に指定したディレクトリにプラグインを設置。設置しただけではダメのようで、callback_whitelist に利用したいプラグイン名を記述する必要があるとのことです。(実施に試してところ、callback_whitelist への記載が不要な挙動だったので引き続き調べたい)

Playbook

引き続き、前の記事で紹介した Datadog のタグを管理するモジュールを利用する Playbook を利用します。

- hosts: localhost
  tasks:
    - name: Test datadog_tags(present)
      datadog_tags:
        state: present
        host: myhost
        tags: 'aa,bb,cc,dd'
        api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    - name: Test datadog_tags(absent)
      datadog_tags:
        state: absent
        host: myhost
        api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

プロビジョニング

$ ansible-playbook datadog.yml
 [WARNING]: Host file not found: /etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Test datadog_tags(present)] **********************************************
changed: [localhost]

TASK [Test datadog_tags(absent)] ***********************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0

CloudWatch Logs を確認

プラグインのデフォルトでは AWS_PROFILE は default が設定され、Log Group は ansible 及び Log Stream が provision が設定されます。

$ aws --profile ${AWS_PROFILE} --region ${AWS_REGION} \
  logs get-log-events \
    --log-group-name ansible --log-stream-name provision | jq '.events|sort_by(.timestamp)|.[-2,-1]'
{
  "ingestionTime": 1490456583837,
  "timestamp": 1490456583257,
  "message": "{'log_action': 'ansible ok', 'status': 'OK', 'host': 'myhost', 'session': 'b8891b28-1171-11e7-9524-3c15c2bdc014', 'ansible_type': 'task', 'ansible_playbook': 'datadog.yml', 'ansible_host': 'localhost', 'ansible_task': TASK: Test datadog_tags(present), 'ansible_result': '{\"changed\": false}'}"
}
{
  "ingestionTime": 1490456583837,
  "timestamp": 1490456583260,
  "message": "{'log_action': 'ansible stats', 'status': 'OK', 'host': 'myhost', 'session': 'b8891b28-1171-11e7-9524-3c15c2bdc014', 'ansible_type': 'finish', 'ansible_playbook': 'datadog.yml', 'ansible_result': '{\"localhost\": {\"ok\": 2, \"failures\": 0, \"unreachable\": 0, \"changed\": 0, \"skipped\": 0}}'}"
}

実装にあたり

Callback Plugin では以下のようなイベントをフックすることが出来ます。

$ grep v2_ plugins/cloudwatch_logs.py
    def v2_playbook_on_start(self, playbook):
    def v2_playbook_on_stats(self, stats):
    def v2_runner_on_ok(self, result, **kwargs):
    def v2_runner_on_skipped(self, result, **kwargs):
    def v2_playbook_on_import_for_host(self, result, imported_file):
    def v2_playbook_on_not_import_for_host(self, result, missing_file):
    def v2_runner_on_failed(self, result, **kwargs):
    def v2_runner_on_unreachable(self, result, **kwargs):
    def v2_runner_on_async_failed(self, result, **kwargs):

また、Python Logging のハンドラで CloudWatch Logs に転送出来る watchtower を利用することで、Logging のインターフェースを利用しています。(参考にした logstash プラグインも同様の実装になっています)

github.com

ということで

CloudWatch Logs に飛ばして(みた)レベルだが、Callback プラグインであれば意外に簡単に実装することが出来ました。

モジュールの実装に関する情報はチラホラ見かけることが出来ますが、プラグインそのものに関する情報があまり見かけない気がしていますが、モジュールやプラグインの側面から Ansible を見てみるのも面白いと考えています。

「Ansible 徹底入門」を読んでる途中だけど Ansible Module(Datadog のタグを管理するモジュール) を作ってみたのメモ

Ansible python datadog

Ansible 徹底入門

www.shoeisha.co.jp

自分自身はまだ読んでいる途中ですが、Ansible をこれから利用しようと考えている方から、各種クラウド環境と組み合わせた一歩踏み込んだ利用を考えて方まで幅広い層の皆さんにお薦め出来ると思います。

ムラムラ

Ansible 徹底入門を読み進めているうちに、ムラムラっと Ansible Module を作ってみたくなったので作ってみました。

Ansible Module について

以下の資料にまとめました。

speakerdeck.com

作った Ansible Module

github.com

Datadog のホストに付与するタグを管理するモジュール。

デモ

デモ環境

$ python --version
Python 2.7.13

$ ansible --version
ansible 2.2.1.0
  config file = /path/to/.ansible.cfg
  configured module search path = Default w/o overrides

モジュールの置き場

以下の何れかのディレクトリに置きます。

Playbook

- hosts: localhost
  tasks:
    - name: Test datadog_tags(present)
      datadog_tags:
        state: present
        host: myhost
        tags: 'aa,bb,cc,dd'
        api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    - name: Test datadog_tags(absent)
      datadog_tags:
        state: absent
        host: myhost
        api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

プロビジョニング

$ ansible-playbook datadog.yml
 [WARNING]: Host file not found: /etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Test datadog_tags(present)] **********************************************
changed: [localhost]

TASK [Test datadog_tags(absent)] ***********************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0

実行例では present して absent しているので、実行結果としてはタグは付与されていないことになるので、一応、present のみ実行した状態は以下のように指定したホストにタグが付与されています。

f:id:inokara:20170326000854p:plain

実装にあたり

  • 引数は AnsibleModule クラスを継承したインスタンスの params に含まれているので適宜取り出して処理すれば良いのは楽
  • モジュール側で冪等性を頑張る必要がある(既に指定したタグが存在している場合には module.exit_json(changed=False) で終了するとか)

参考

以下のリンクを参考にさせて頂くことで、思いのほか簡単に Ansible Module を作ることが出来た。

ありがとうございました。

2017 年 03 月 25 日(土)

日々

ジョギング

日課

  • (腕立て x 30 + 腹筋 x 30) x3

なんさん

  • 10 年以上前に同じ会社だったなんさんと博多で会う
  • 同じ会社だった時はあまり話しをしたことが無かったけど、当時のことを色々と覚えていて会話は弾んだと思う
  • 次回はなんさんの旦那さんも交えて博多で呑む予定

夕飯

  • 串かつの串匠
  • 美味しかったけど服に付く臭いが凄いという…

小ネタ道場一本勝負 〜 Python Logging で CloudWatch Logs にログを送信したいんですけど 〜

python aws CloudWatch Logs 小ネタ道場一本勝負

たのもう

Python の Logging モジュールで CloudWatch Logs にログを転送出来るやつ(ハンドラ)があればいいのになーと思っていたら既に在ったので嬉しかったです。

github.com

一本

watchtower のインストール

pip install watchtower

サンプル

import watchtower, logging
import boto3

session = boto3.Session(profile_name='your-profile')

logging.basicConfig(level=logging.WARN)
logger = logging.getLogger(__name__)
logger.addHandler(watchtower.CloudWatchLogHandler(
    boto3_session=session,
    log_group='your-log-group',
    stream_name='your-log-stream')
)
logger.info(dict(level="info", details={"foo":"info"}))
logger.warn(dict(level="warn", details={"foo":"warn"}))
logger.error(dict(level="error", details={"foo":"error"}))

サンプルを実行

$ python --version
Python 3.6.0
$ python log_test.py
WARNING:__main__:{'level': 'warn', 'details': {'foo': 'warn'}}
ERROR:__main__:{'level': 'error', 'details': {'foo': 'error'}}

CloudWatch Logs を確認してみます。

$ aws --profile your-profile --region ap-northeast-1 logs get-log-events \
  --log-group-name your-log-group \
  --log-stream-name your-log-stream \
  | jq '.events|sort_by(.timestamp)|.[-2,0]'
{
  "ingestionTime": 1490399839605,
  "timestamp": 1490399841112,
  "message": "{'level': 'warn', 'details': {'foo': 'warn'}}"
}
{
  "ingestionTime": 1490399839605,
  "timestamp": 1490399841619,
  "message": "{'level': 'error', 'details': {'foo': 'error'}}"
}

有難うございました

github.com

2017 年 03 月 24 日(金)

日々

ああ、金曜日なんだ

  • 今週は早いな

ジョギング

日課

  • (腕立て x 30 + 腹筋 x 30) x 3