moto の 1.3.15 でエラー

こんにちは。

概要

python から AWS のリソースを操作したいとき、 SDK である boto3 を利用してる方も多いと思います。 その boto3 を mock してくれる大変ありがたいライブラリである、 moto ですが、 09/08 にリリースされた ver.1.3.15 で、必要な依存ライブラリがインストールされなくなりテストに失敗するケースが出ているようです。 github.com

起こったこと

かくいう私も、 S3 と Cognito のモックでエラーが出てしまいました。 GitHub のブランチに Push すると CodePipeline が動きはじめ、CodeBuild で pytest を実行後、 serverless framework でデプロイをしています。

その pytest の部分がエラーになってしまい、デプロイ失敗となっていました。

なぜ気づいたか

なぜ moto が原因かと気づいたかというと、 * 同じソースコードを09/07 にデプロイしたときは問題なく通っていた * ソースコードやビルド環境は変更していない * 使用しているライブラリは Pipfile で管理しており、バージョン固定していない(ビルド時の最新を使用する)

利用しているライブラリの最終更新はないかな?と調べたら、ちょうど moto がバージョンアップしていました。 そこで、 Pipfile にてバージョンを 1.3.14 に固定してデプロイしたらテスト成功。 これだ。となった次第です。

対応

ひとまずはバージョン固定でデプロイすることにしました。 moto は現在修正作業が行われているので、次のバージョンを待ちましょう。

教訓

デプロイ時のバージョンには気を付けましょう。 バージョン固定をするべきかどうか。このあたりもきちんと考えて方針を決めたいですね。

最後に

moto は AWS 関連の開発を行う上で非常に便利なライブラリです。 これからもお世話になります!

Windows10 Home に Docker を導入して Cmder から利用できるようにする

Install Docker Toolbox on Windows | Docker Documentation の手順に従います

前提

OS: Windows 10 Home 64bit

ダウンロード

Toolbox Releases で最新の DockerToolbox-19.03.1.exe をダウンロードする f:id:dr3mms:20200905112053p:plain

インストール

ダウンロードした DockerToolbox-19.03.1.exe管理者として実行 する f:id:dr3mms:20200905112136p:plain f:id:dr3mms:20200905112148p:plain インストール先は任意に設定する f:id:dr3mms:20200905112152p:plain ※私は C:\Users\{ユーザ名}\Documents\Program\DockerToolbox にしました

f:id:dr3mms:20200905112207p:plain Git for Windows はインストール済みのためチェックを外します f:id:dr3mms:20200905112240p:plain f:id:dr3mms:20200905112311p:plain

image.png インストール確認は インストール を選択

f:id:dr3mms:20200905112326p:plain 完了です

起動設定(ショートカット)

ショートカットを右クリックでプロパティを開き、 リンク先 の「--login -i」以降をコピーしておく f:id:dr3mms:20200905112517p:plain

※私の環境 "C:\Users\{ユーザ名}\Documents\Program\DockerToolbox\start.sh"

起動設定(Cmder)

右下の設定ボタンをクリック ⇒ Settings StartupTasks f:id:dr3mms:20200905112903p:plain

通常Bashで使用している {bash::bash As Admin} を選択し、「Clone」をクリック

f:id:dr3mms:20200905113018p:plain 名前を docker として右下のテキストエリアの「--login -i」以降にコピーしておいたパスを記入 Save settings をクリックし保存する

f:id:dr3mms:20200905171253p:plain Cmder の右下 + ボタンをクリックし新しいコンソールを開く 上の Startup command of {Task} name... でさきほど設定した docker を選択し、 Start で開始する

f:id:dr3mms:20200905171325p:plain docker コマンドが実行できるようになる

補足

Windows をシャットダウンする際に、 VirtualBox Interface がシャットダウンの邪魔をすることがある。 その場合は、「VBoxSVC.exe」を停止する。 ※ プロセスの強制停止になるので、自己責任でお願いします f:id:dr3mms:20200905112711p:plain

以下のファイルを作成しておいて、 Cmder から実行することでプロセスを停止することもできる。 StopVBoxSVC.sh

Stop-Process -Name VBoxSVC

実行

powershell ./StopVBoxSVC.sh

参考

Windows 10 Home のための、Docker Toolbox をインストールして WSL から使う方法 | ラボラジアン

Python3 で日付処理覚書

概要

AWS のリソースデータを PythonSDK である boto3 を使って取得した場合、 日付データは datetime.datetime(2020, 8, 23, 10, 14, 9, tzinfo=tzlocal()) のように取得される。

その値を dateutil.tz を利用してタイムゾーンを意識した値として利用する方法の覚書。

※dateutil は AWS Lambda では標準で使用できる

dateutil - powerful extensions to datetime — dateutil 2.8.1 documentation

datetime の timezone ごとの値

ソース

import datetime
import dateutil.tz

# 現在時刻
print('----- local')
datetime_local = datetime.datetime.now(dateutil.tz.tzlocal())
print(repr(datetime_local))
print(datetime_local)

print('----- utc')
datetime_utc = datetime.datetime.now(dateutil.tz.tzutc())
print(repr(datetime_utc))
print(datetime_utc)

print('----- jst')
datetime_jst = datetime.datetime.now(dateutil.tz.gettz('Asia/Tokyo'))
print(repr(datetime_jst))
print(datetime_jst)

結果(タイムゾーンUTC の環境)

----- local
datetime.datetime(2020, 8, 23, 12, 25, 33, 93313, tzinfo=tzlocal())
2020-08-23 12:25:33.093313+00:00
----- utc
datetime.datetime(2020, 8, 23, 12, 25, 33, 93706, tzinfo=tzutc())
2020-08-23 12:25:33.093706+00:00
----- jst
datetime.datetime(2020, 8, 23, 21, 25, 33, 94216, tzinfo=tzfile('/usr/share/zoneinfo/Asia/Tokyo'))
2020-08-23 21:25:33.094216+09:00

結果(タイムゾーンJST の環境)

----- local
datetime.datetime(2020, 8, 23, 21, 26, 59, 65988, tzinfo=tzlocal())             
2020-08-23 21:26:59.065988+09:00                                                
----- utc
datetime.datetime(2020, 8, 23, 12, 26, 59, 66953, tzinfo=tzutc())               
2020-08-23 12:26:59.066953+00:00                                                
----- jst
datetime.datetime(2020, 8, 23, 21, 26, 59, 163724, tzinfo=tzfile('Japan'))      
2020-08-23 21:26:59.163724+09:00                                                

Local から UTC / JST への変換

ソース

import datetime
import dateutil.tz

# 変換
datetime_base = datetime.datetime.now(dateutil.tz.tzlocal())
print('----- Local')
datetime_local = datetime_base
print(repr(datetime_local))
print(datetime_local)
print('----- UTC')
datetime_utc = datetime_base.astimezone(dateutil.tz.tzutc())
print(repr(datetime_utc))
print(datetime_utc)
print('----- JST')
datetime_jst = datetime_base.astimezone(dateutil.tz.gettz('Asia/Tokyo'))
print(repr(datetime_jst))
print(datetime_jst)

結果(タイムゾーンUTC の環境)

----- Local
datetime.datetime(2020, 8, 23, 12, 53, 46, 149610, tzinfo=tzlocal())
2020-08-23 12:53:46.149610+00:00
----- UTC
datetime.datetime(2020, 8, 23, 12, 53, 46, 149610, tzinfo=tzutc())
2020-08-23 12:53:46.149610+00:00
----- JST
datetime.datetime(2020, 8, 23, 21, 53, 46, 149610, tzinfo=tzfile('/usr/share/zoneinfo/Asia/Tokyo'))
2020-08-23 21:53:46.149610+09:00

結果(タイムゾーンJST の環境)

----- Local
datetime.datetime(2020, 8, 23, 21, 53, 47, 787886, tzinfo=tzlocal())
2020-08-23 21:53:47.787886+09:00
----- UTC
datetime.datetime(2020, 8, 23, 12, 53, 47, 787886, tzinfo=tzutc())
2020-08-23 12:53:47.787886+00:00
----- JST
datetime.datetime(2020, 8, 23, 21, 53, 47, 787886, tzinfo=tzfile('Japan'))
2020-08-23 21:53:47.787886+09:00                                             

オマケ:byte文字列から datetime への変換

dns.resolver などで証明書の有効期限を取得したときなど

ソース

import datetime
import dateutil.tz

byte_datetime = b'20210708151000Z'
# 文字列に
print(byte_datetime.decode('ascii'))
# 「Z」を「+00:00」としてから datetime に変換
not_after = datetime.datetime.strptime(byte_datetime.decode('ascii').replace('Z', '+00:00'), '%Y%m%d%H%M%S%z')

print(repr(not_after))
print('----- Local')
datetime_local = not_after.astimezone(dateutil.tz.tzlocal())
print(datetime_local)
print(datetime_local.strftime('%Y/%m/%d'))
print('----- UTC')
datetime_utc = not_after.astimezone(dateutil.tz.tzutc())
print(datetime_utc)
print(datetime_utc.strftime('%Y/%m/%d'))
print('----- JST')
datetime_local = not_after.astimezone(dateutil.tz.gettz('Asia/Tokyo'))
print(datetime_local)
print(datetime_local.strftime('%Y/%m/%d'))

結果(タイムゾーンUTC の環境)

20210708151000Z
datetime.datetime(2021, 7, 8, 15, 10, tzinfo=datetime.timezone.utc)
----- Local
2021-07-08 15:10:00+00:00
2021/07/08
----- UTC
2021-07-08 15:10:00+00:00
2021/07/08
----- JST
2021-07-09 00:10:00+09:00
2021/07/09

結果(タイムゾーンJST の環境)

20210708151000Z
datetime.datetime(2021, 7, 8, 15, 10, tzinfo=datetime.timezone.utc)
----- Local
2021-07-09 00:10:00+09:00
2021/07/09
----- UTC
2021-07-08 15:10:00+00:00
2021/07/08
----- JST
2021-07-09 00:10:00+09:00
2021/07/09