AWS Cloud9上で作成したLambda関数で環境変数を利用する
Lambdaコード内で、設定値を切り替えたい場合があります。
例えば、本番環境と検証環境で接続先を変えたい、などです。
このような場合、環境変数に値を設定して、コード内から環境変数を参照します。
特定の言語に依存せず参照できますし、コードから定数が消えるので、セキュリティ的にもGoodです。
AWS Serverless Application Model
しかし .bash_profile
に環境変数を追加しても、Lambda関数内から取得はできません。
AWS Cloud9 EC2環境には、AWS Serverless Application Model (SAM) がデフォルトでインストールされています。
$ sam --version A newer version of the AWS SAM CLI is available! Your version: 0.2.11 Latest version: 0.6.0 See https://github.com/awslabs/aws-sam-local for upgrade instructions sam version 0.2.11
実は、AWS Cloud9上で作成したLambda関数は、このSAMを利用しており、Lambda関数内から環境変数を利用する場合は、SAM用のテンプレート template.yaml
に追記する必要があります。
ローカル上にLambda関数を作成
環境変数を定義して、コードから参照できるか試してみましょう。
まずはLambda関数を作成します。
右側サイドバーにある、[AWS Resources] を選択して [AWSリソース] ウィンドウを開き、[λ+] ボタンをクリックします。
- 関数名
- checkSite
- アプリケーション名
- CheckSite
- ランタイム
- Python 3.6
- 設計図
- lambda-canary-python3
- 指定したサイトを定期的にチェック、テスト失敗時にエラー
- lambda-canary-python3
- 関数トリガー
- none
- メモリ
- 128MB
- ロール
- 自動生成(Automatically generate role)
AWS Cloud9上に、CheckSite
ディレクトリが作成されます。
Lambda関数
作成されたLambda関数です。
デフォルトの状態で、環境変数を参照しています。 このまま利用します。
lambda_function.py
import os from datetime import datetime from urllib.request import urlopen SITE = os.environ['site'] # URL of the site to check, stored in the site environment variable EXPECTED = os.environ['expected'] # String expected to be on the page, stored in the expected environment variable def validate(res): '''Return False to trigger the canary Currently this simply checks whether the EXPECTED string is present. However, you could modify this to perform any number of arbitrary checks on the contents of SITE. ''' return EXPECTED in res def lambda_handler(event, context): print('Checking {} at {}...'.format(SITE, event['time'])) try: if not validate(str(urlopen(SITE).read())): raise Exception('Validation failed') except: print('Check failed!') raise else: print('Check passed!') return event['time'] finally: print('Check complete at {}'.format(str(datetime.now())))
- 環境変数
site
、expected
から値を取得- site: チェックするサイトのURL
- expected: HTMLに含むチェックするキーワード
- 入力値
- time: チェックする日時を指定
template.yaml
[環境] ウィンドウから、CheckSiteディレクトリ直下の template.yaml
をダブルクリックして、SAM用のテンプレートを [タブ] ウィンドウに表示します。
Propertiesに Environment
/ Variables
キーに、環境変数を追記して保存します。
AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' Description: An AWS Serverless Specification template describing your function. Resources: checkSite: Type: 'AWS::Serverless::Function' Properties: Handler: checkSite/lambda_function.lambda_handler Runtime: python3.6 Description: '' MemorySize: 128 Timeout: 15 CodeUri: .debug/ Environment: Variables: site: 'https://oreout.hatenablog.com' expected: '2018-09-29'
ローカル上のLambda関数を実行
正しく動作するか、ローカル上で確認をします。
- [Local Functions] 内のLambda関数checkSiteを右クリックしてメニュー表示
- [Run] - [Run Local] を選択
- [Payload] ペインに入力値を設定して [Run] ボタンをクリック
ブログトップに指定した日付のエントリがあるかどうかを確認します。
見つかった場合
環境変数 expected
にトップページに存在するキーワードを設定
Payload
{ "time": "2018/09/30 17:00" }
Response
"2018/09/30 17:00"
見つからなかった場合
環境変数 expected
にトップページに存在しないキーワードを設定
Payload
{ "time": "2018/09/30 17:00" }
Response
{ "errorMessage": "Validation failed", "errorType": "Exception", "stackTrace": [ [ "/var/task/checkSite/lambda_function.py", 24, "lambda_handler", "raise Exception('Validation failed')" ] ] }
意図した通りに実行されました。
AWS上でLambda関数を実行
ローカル上のLambda関数をAWS上にデプロイして実行します。
デプロイ
- [Local Functions] 内のLambda関数checkSiteを右クリックしてメニュー表示
- [Deploy] を選択
Lambda関数のリモート実行
- [Local Functions] 内のLambda関数checkSiteを右クリックしてメニュー表示
- [Run] - [Run Remote] を選択
AWS Lambdaコンソール画面上で、環境変数が設定されていることが確認できます。
参考
- AWSドキュメント
AWS Cloud9上で作成したLambda関数でPython3外部モジュールを利用する
Lambda関数でPythonの外部モジュールを利用する場合、Lambda関数デプロイパッケージに含める必要があります。
ローカルの場合は、zipにまとめてAWS Lambdaへアップロードする必要がありますが、AWS Cloud9上からデプロイする場合(つまりSAM)は簡単です。
Lambda関数を作成・デプロイ・実行の仕方は、下記のエントリを参照してください。
ローカル上にLambda関数を作成
ローカル上にLambda関数を作成します。
右側サイドバーにある、[AWS Resources] を選択して [AWSリソース] ウィンドウを開き、[λ+] ボタンをクリックします。
- 関数名
- getLastDayOfNextMonth
- アプリケーション名
- GetLastDayOfNextMonth
- ランタイム
- Python 3.6
- 設計図
- empty-python
- 関数トリガー
- none
- メモリ
- 128MB
- ロール
- 自動生成(Automatically generate role)
AWS Cloud9上に、GetLastDayOfNextMonth
ディレクトリが作成されます。
年月を指定して翌月末日を取得するLambda関数
lambda_function.py
を下記コードに差し替えて、保存 (Command+S) します。
lambda_function.py
import datetime from dateutil import relativedelta def lambda_handler(event, context): today = datetime.date.today() first_day = datetime.date(event.get('year', today.year), event.get('month', today.month), 1) last_day = first_day + relativedelta.relativedelta(months=+1, day=99) return { 'year' : last_day.year, 'month': last_day.month, 'day': last_day.day }
今回は、日付操作用のdateutils
モジュールを利用します。
- 入力に年月を指定
- 省略した場合は当日の年月をデフォルト値に設定
- 戻り値に翌月末日の年月日を返却
- 2018年12月なら、2019年1月31日
外部モジュールのインストール
dateutils
モジュールをインストールします。
ターミナルから、GetLastDayOfNextMonth
ディレクトリに移動してインストールします。
$ cd GetLastDayOfNextMonth/ $ pip-3.6 install dateutils -t .
-t
はどこにインストールするかのターゲットを、.
はカレントディレクトリを意味します。
必要なモジュールがインストールされました。
ローカル上のLambda関数を実行
正しく動作するか、ローカル上で確認をします。
- [Local Functions] 内のLambda関数getLastDayOfNextMonthを右クリックしてメニュー表示
- [Run] - [Run Local] を選択
- [Payload] ペインに入力値を設定して [Run] ボタンをクリック
Payload
{ "year": 2018, "month": 12 }
Response
{ "year": 2019, "month": 1, "day": 31 }
正しく表示されました。
AWS上でLambda関数を実行
ローカル上のLambda関数をAWS上にデプロイして実行します。
デプロイ
- [Local Functions] 内のLambda関数getLastDayOfNextMonthを右クリックしてメニュー表示
- [Deploy] を選択
Lambda関数のリモート実行
- [Local Functions] 内のLambda関数getLastDayOfNextMonthを右クリックしてメニュー表示
- [Run] - [Run Remote] を選択
AWS Lambdaコンソール画面上で、モジュールがデプロイされていることが確認できます。
参考
- AWSドキュメント
AWS Cloud9からPython3で作成したLambda関数を実行する
AWS Cloud9上で、Lambda関数を作成して実行します。
大まかな流れは下記になります。
- ローカル上にLambda関数を作成
- ローカル上のLambda関数を(デバッグ)実行
- AWS上にLambda関数をデプロイして実行
ここでいうローカル
とは、ブラウザで起動したCloud9環境
を指します。
Lambda関数はPython3で作成します。
Python3の構築は下記エントリを参照してください。
AWS Lambdaの連携先リージョン
その前にLambdaの連携先リージョンを変更します。
EC2環境のデフォルトでは、Lambdaの連携先リージョンは、AWS Cloud9を起動したリージョンと同じになります。
AWS Cloud9 EC2環境をシンガポールリージョンで作成した場合、Lambdaや実行ロール、それを作成するCloudFormationは、同じシンガポールリージョンに作成されます。
今回は、Lambdaの連携先をシンガポールリージョン
から東京リージョン
に変更します。
- ツールバー右側の歯車アイコンを選択して、プロジェクト設定を開く
- [AWS SETTINGS] を選択
- [AWS Region] を
Asia Pacific (Tokyo)
に変更
特に設定反映ボタンはありません。
ローカル上にLambda関数を作成
ローカル上、つまりAWS Cloud9 環境上に、Lambda関数を作成します。
右側サイドバーにある、[AWS Resources]を選択して [AWSリソース] ウィンドウを開きます。
ウィンドウ右上に、プロジェクト設定で選択した東京リージョン ap-northeast-1
が表示されています。
それではLambda関数を作成しましょう。 オレンジ色の [λ+] ボタンをクリックします。
サーバーレスアプリケーションの作成
関数名
とアプリケーション名
を入力します。
ここで入力した関数名
とアプリケーション名
は、Cloud9環境内のディレクトリ名、AWS Lambda関数名に使われます。
ランタイム
(言語とバージョン)とテンプレートとなる設計図
を選択します。
- ランタイムから
Python 3.6
を選択 - 設計図として
hello-world-python3
を選択 - [Next] ボタンをクリック
関数トリガー
では、API Gateway と連携するかを設定します。
今回はデフォルトのnone
のまま、[Next] ボタンをクリックします。
メモリ
とロール
を選択します。
今回はデフォルトのまま、[Next] ボタンをクリックします。
ロール
は自動生成されます。
確認画面です。
問題がなければ、[Finish] ボタンをクリックします。
ローカル上にいくつかのファイルが作成され、指定したリージョンにAWS Lambda関数(とロール)が作成されます。
Lambdaコードの修正
環境ウィンドウ内のlambda_function.py
をダブルクリックして、タブウィンドウにLambda関数を表示します。
下記コードに差し替えて、保存 (Command+S) します。
lambda_function.py
import json print('Loading function') def lambda_handler(event, context): message = 'Hello {} {}!'.format(event['first_name'], event['last_name']) return { 'message' : message }
入力された名前と文字を連結して返すだけのシンプルなコードです。
ローカル上のLambda関数を実行
作成したLambda関数をローカル上で実行します。
操作は [AWSリソース] ウィンドウから行います。
- [Local Functions] 内のLambda関数
myHelloWorld
を右クリックしてメニュー表示 - [Run] - [Run Local] を選択
[実行] タブが表示されます。
[実行] タブ内の [Payload] ペインで、JSON形式で入力データを登録します。
{ "first_name": "太郎", "last_name": "山田" }
[Run] ボタンをクリックすると、結果が下に表示されます。
ローカル上でLambda関数をデバッグする
今度はデバッグ実行してみましょう。
行番号の横をクリックして、ブレークポイントを貼ります。 赤い円が表示されます。
[Run] ボタン右側の [バグ] アイコンをクリックします。アイコンが灰色から緑に切り替わります。
この状態で、[Run] ボタンをクリックします。
ブレークポイントでコードが一時停止され、[デバッガー] ウィンドウに現在の値が表示されます。
AWS上でLambda関数を実行
ローカル上のLambda関数をAWS上にデプロイして実行します。
操作は [AWSリソース] ウィンドウから行います。
AWS上にデプロイ
- [Local Functions] 内のLambda関数
myHelloWorld
を右クリックしてメニュー表示 - [Deploy] を選択
指定したリージョンへLambda関数がデプロイされます。
Lambda関数のリモート実行
- [Local Functions] 内のLambda関数
myHelloWorld
を右クリックしてメニュー表示 - [Run] - [Run Remote] を選択
[実行] タブ内の接続先が、Lambda (remote)
になっていることを確認して、[Run] ボタンをクリックします。
[結果] ペインにステータスコード200
が表示されていれば成功です。
削除
作成したLambda関数を削除する場合、AWS側のリソースとローカル上の両方を削除する必要があります。
AWS側のリソース
CloudFormationから削除します。
[サービス] - [管理ツール] - [CloudFormation] からスタックを削除します。
ローカル上
AWS Cloud9 [環境] パネル上のアプリケーションディレクトリを右クリックして削除します。
まとめ
AWS Cloud9を利用すれば、Lamba関数を簡単にデバッグすることができます。
PC上にローカル環境(aws-sam-cli)を構築する必要はありません。
今回は触れていませんが、既存のLamba関数をAWS Cloud9上にインポートすることもできます。
気軽に試してみましょう。
参考
- AWSドキュメント
AWS Cloud9 IDE内でWebアプリケーションを表示する
AWS Cloud9 IDE内で、実行中のWebアプリケーションを表示することができます。
今回は、Flaskを利用して確認します。
FlaskはPythonの軽量なWebアプリケーションフレームワークです。
Python3の構築は下記エントリを参照してください。
Flaskのインストール
Flaskをpip経由でインストールします。
$ sudo pip-3.6 install flask Collecting flask Downloading 略 Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24
コードの作成
確認用のテストコードを作成します。
メニューバー [File] - [New From Template] - [Python File] を選択します。
タブウィンドウに新規エディタが表示されるので、下記のコードを貼り付けて保存します。
ポートは8080
を指定します。
test.py
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run(debug=True, port=8080)
IDE内からWebアプリケーションを表示するには、ポート8080
を指定する必要があります。
それ以外のポート番号だとエラーが表示されます。
※ドキュメントだとポート番号8081
、8082
も許可してるっぽいけど、エラーになる。なぜ?
Webアプリケーションの表示
- [Run]ボタンを選択
- Webアプリケーションが実行 (Running on http://127.0.0.1:8080/)
- [Preview]ボタンを選択
- [Preview Running Application] を選択
IDE上にアプリケーションプレビュータブが開かれ、Hello World!
と表示されました。
アプリケーションプレビュータブ
- プレビューをリロードします。
- アドレスバー。URLを入力します。
- プレビューを新しいウィンドウで開きます。
参考
AWS Cloud9でPython3の環境を構築する
EC2環境を作成した直後はPython2系を利用できます。
Python3系を利用するためにはプロジェクト設定を変更する必要があります。
EC2環境の構築は下記エントリを参照してください。
プロジェクト設定
Python用の設定項目を表示します。
- メニューバー右側の歯車アイコンを選択
- プロジェクト設定画面 [PROJECT] - [Python Support] を選択
Python Version
使用するPythonのバージョンを指定します。
Python3
に変更します。
注意点として、ここで設定したPythonのバージョンは、IDE上で実行したコード用(ランナー)であって、ターミナル上のPythonとは関係ありません。
ターミナル上のPythonは、エイリアス変更しない限り2.7系のままです。
$ python -V
Python 2.7.14
Enable Python code completion
ONの場合、Pythonコード補完を有効にします。
デフォルトではONです。
この項目は PYTHONPATH
のパスを参照します。
コード補完が効いていない場合、パスが間違っている可能性があります。
デフォルト値
/usr/local/lib/python2.7/dist-packages:/usr/local/lib/python3.4/dist-packages:/usr/local/lib/python3.5/dist-packages
パスをコロン(:)で連結します。
デフォルトでは2.7
と3.4
、3.5
を参照していますが、インストールされているPythonを確認すると2.7
と3.6
です。(2018年9月25時点)
$ ls /usr/local/lib -l total 8 drwxr-xr-x 3 root root 4096 Jan 15 2018 python2.7 drwxr-xr-x 3 root root 4096 Sep 13 11:57 python3.6
Python3系でコード補完をするためには、PYTHONPATH
値を修正します。
修正した値
/usr/local/lib/python2.7/dist-packages:/usr/local/lib/python3.6/dist-packages
プロジェクト設定の保存場所
プロジェクト設定画面で設定した値は、JSON形式でproject.settings
ファイルに保存されます。
- 環境ウィンドウにある歯車アイコンを選択
- [Show Hidden Files]をチェックして隠しファイルを表示
.c9
フォルダ内のproject.settings
ファイルをダブルクリック- エディタタブ上に表示された、設定ファイル
python
項目を確認
自分の環境では、プロジェクト設定からPythonのバージョンを変更したにも関わらず、反映されないケースがありました。 (リロードすると元に戻る)
その場合は、直接project.settings
ファイルを編集して保存しました。
Pythonバージョン確認
新規にファイルを作成してバージョンを確認してみます。
コード補完が効いているか確認をしてください。
test.py
import sys print(sys.version_info)
ファイルを保存して[Run]ボタンをクリックして実行します。
ランナーウィンドウにバージョンが表示されます。
Python3の場合
Python2の場合
ランナーウィンドウのRunner:言語
ボタンから直接変更もできます。
ターミナル
ターミナルからPythonのバージョンを確認します。
エイリアス変更はご自由に。
$ python -V Python 2.7.14 $ pip -V pip 9.0.3 from /usr/lib/python2.7/dist-packages (python 2.7) $ python3 -V Python 3.6.5 $ pip-3.6 -V pip 9.0.3 from /usr/lib/python3.6/dist-packages (python 3.6)
参考
- AWSドキュメント
- AWS Cloud9 Integrated Development Environment (IDE) でプロジェクト設定を操作する
AWS Cloud9とCodeCommitを統合する
AWS Cloud9 内から AWS CodeCommit リポジトリでコード管理を行うことができます。
AWS Cloud9 EC2環境を起動します。
AWS CodeCommitリポジトリは事前に用意しておいてください。
AWS Cloud9 EC2環境の構築は、下記エントリを参照してください。
AWS CodeCommitの前準備は、下記エントリを参照してください。
Gitの設定
AWS Cloud9内のターミナルウィンドウから、gitがインストールされていることを確認します。
$ git --version
git version 2.14.4
git configコマンドで、Gitコミットと関連付けるユーザー名
とメールアドレス
を設定します。
$ git config --global user.name "Hoge Fuga" $ git config --global user.email hoge-fuga@example.com
AWS CLIの認証情報ヘルパー設定
ターミナルウィンドウから、下記のコマンドを入力し、HTTPS接続用のAWS CLIの認証情報ヘルパーを設定します。
認証ヘルパーを設定すると、毎回ユーザーとパスワードを入力する手間がなくなります。
$ git config --global credential.helper '!aws codecommit credential-helper $@' $ git config --global credential.UseHttpPath true
設定した値は、git config -l
で確認できます。
$ git config -l core.editor=/usr/bin/nano user.name=Hoge Fuga user.email=hoge-fuga@example.com credential.helper=!aws codecommit credential-helper $@ credential.usehttppath=true
CodeCommitリポジトリの作成
リポジトリを作成します。
$ aws codecommit create-repository --repository-name SampleRepo { "repositoryMetadata": { "repositoryName": "SampleRepo", "cloneUrlSsh": "ssh://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/SampleRepo", "lastModifiedDate": 1536974158.19, "repositoryId": "905607e6-13f3-4a0e-698b-b1d0c6bd6146", "cloneUrlHttp": "https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/SampleRepo", "creationDate": 1536974158.19, "Arn": "arn:aws:codecommit:ap-southeast-1:123456789012:SampleRepo", "accountId": "123456789012" } }
Cloud9を起動したリージョン上にリポジトリが作成されます。
別のリージョンに作成する場合は、--region
オプションを指定します。
$ aws codecommit create-repository --repository-name SampleRepo --region ap-northeast-1
CodeCommitリポジトリのクローンを作成
ターミナルウィンドウから、git cloneコマンドを実行します。
$ git clone https://git-codecommit.<リージョン>.amazonaws.com/v1/repos/<リポジトリ名>
URLは、 CodeCommitのダッシュボードのURL列のアイコンから HTTPS
を選択することでコピーできます。
参考
- AWSドキュメント
技術ブログ始めて2ヶ月たちました
早いもので、ブログを立ち上げてから2ヶ月が経ちました。
当初は、週に1〜2エントリを目標にしていましたが、気がつけば 30エントリ。
2日に1エントリのペース。
内容は別にしても、まずまずです。
「ブログ面倒だからやめるかぁ、どうせ無料だし」
と、言い訳するのを防ぐため、すぐにPro(1年払い)に切り替えました。
技術ブログを書く目的
大きく2つあります。
インプットだけでは忘れやすい
自分はインプットはそこそこしている方だと思います。
電車の中でスマホで調べたり、自宅で気になる技術を調査したり。。
それでも、使わないと段々と忘れてしまいます。 誰だってそうだと思うんですよね。年をとるとなおさらです。
そこで、ブログでアウトプットです。
このブログを見ている人はあまりいませんが、インプットした情報をまとめて、文章構成を考えて、間違いがないかを確認する。
この工程があるから、断然インプットだけよりかは、忘れにくくなります。
まぁ、使わなかったら、結局忘れるんですけどねw
文書をまとめる力をつけたい
文章をまとめる力がつけば、普段の仕事の質も上がるし、プレゼンや人に教える時にもメリットがあると思います。
まだまだ、まとめる力がついていないのが残念です。
でも継続していけば、少しずつまとめる力が付いてくる、と思っています。
量は質に変化する
とポジティブに考えてます。