2016年3月28日月曜日

AWS EC2 の インスタンスIDにマッチする正規表現が欲しかったので試行錯誤した結果

得られた正規表現

'^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$'



背景


今の勤務先ではAWS系インフラエンジニアとしてAWSの管理全般を行っています。
昨今のクラウド全盛期においては運用業務の各種自動化が大事ということで、Python + AWS SDK(Boto3)で、AWS管理自動化プログラミングを少しずつ進めています。
AWSの操作はEC2に関するものが多く、EC2のインスタンスIDを引数に与えるものが多くなっているので、インスタンスIDが正しく入力に与えられているかをバリデーションできたらいいなと思い、ちょっと探してみた結果、以下のような正規表現を得ることができました。もっといい案がありましたら教えてください。
数ヶ月前に、インスタンスID及びAMI IDの文字数拡張がアナウンスされています。なので、「i-(英数字8桁)」の場合と、「i-(英数字17桁)」の場合に対応する必要がありました。今回はそれに対応できるようになりました。

得られた正規表現をPythonで使いたい


Pythonで使う時には、標準で用意されている re というモジュールをインポートして、 search() を使うことで、与えられた文字列が正規表現にマッチしているかどうかを確認することができます。
「i-」の後ろが8桁の英数字か、17文字の英数字の時のみ、オブジェクトが返ってくるので、そのオブジェクトの存在を確認すれば、インスタンスIDが実在するかはどうであれ、少なくとも形式に沿った値であるということがわかります。

>>> 
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-0')                                                                                                                                          
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-03')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033a')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag6')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h')
<_sre .sre_match="" 10="" match="i-033ag67h" object="" span="(0,">
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8r')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rb')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0t')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx')
<_sre .sre_match="" 19="" match="i-033ag67h8rbm1l0tx" object="" span="(0,">
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx0')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx05')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx05f')
>>> 
>>> 

書いている時に思ったけど…

describe-instance みたいな、インスタンスIDを引数にEC2の情報を取得する関数があるんだから、それを与えられたインスタンスIDで実行してみればいいだけのような気もしますね。でもその場合はAWS APIへの通信が1往復増えるため、繰り返し件数が多いバッチなどを書く時には処理合計時間が大きくなってしまうネックはありますね。

0 件のコメント:

コメントを投稿