lambda入門(Node) – serverless flameworkを使ってみる

こんにちわ、lambdaとslackを連携させて
あれこれやってみたいと思っている@smith_30 です

ひとまず今回は、lambdaを使うにあたりやったことを書き残しておきたいと思います

使ったもの

OS: Mac

  • Node
    私がlambdaを書くに当たってつかえるのはjavascriptだけだったので。

  • phpstorm
    php書く際にお世話になっています、
    フロントエンド範囲だったら大体なんでも便利にしてくれます。

  • eslint
    lambdaがサポートしているNodeのバージョンはv4なので
    es6で書けるため。
    phpstormに読み込ませて、文法を校正してもらう。

  • serverless flamework
    https://github.com/serverless/serverless

準備

phpstorm にeslintの設定を行う

eslintの設定は、google javascript style guideのものを使う

  • インストール
$ npm install -g eslint eslint-config-google
  • 設定ファイル作成
eslintrc.json
{
  "parserOptions": {
    "ecmaVersion": 6
  },
  "extends": ["google"],
  "rules": {
    // Additional, per-project rules...
  }
}
  • phpstormに読ませる

e3d10d243ff703bb8347a2eb1956646e.png

serverless flamework

amazonが出しているserverless flamework的なやつもあるのですが
gcpとかその他クラウドサービスでもserverlessで何かという場合に
柔軟でありたいと思いこちらにしました。

serverless.ymlのproviderのnameあたりいじればいい。
awsでないsampleはこちらから

  • インストール
$ npm install -g serverless
  • awsのIAMを操作。Credential作成
  1. IAMのページにアクセス→ユーザータブをクリック→ユーザーを追加をクリック

  2. アクセスの種類は「プログラムによるアクセス」

  3. 既存のポリシーを直接アタッチ、AdministratorAccessを選択

  4. ユーザーの作成を実行

  • マシンに環境変数を設定
export AWS_ACCESS_KEY_ID=<your-key-here>
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>
  • プロジェクト作成(スクラッチで始める)
  • Or Existing Servicesから既存のプロジェクトを持ってきて使える
$ serverless create --template aws-nodejs --path testProject
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/serverless/testProject"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  ___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.8.0
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"

  • サービスのデプロイ
$ serverless deploy -v

プロジェクト内の全ての変更を反映させたいとき
(serverless.ymlの変更など)

serverless.ymlで指定されているデフォルトのリージョンはus-east-1なので
好きなところに編集しておくとよろしいかと。

  • lambda function のデプロイ
$ serverless deploy function -f hello

ここ以降のhelloは、プロジェクト作成時に入っているファイルを指す

handler.js
'use strict';

module.exports.hello = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  callback(null, response);

  // Use this code if you don't use the http event with the LAMBDA-PROXY integration
  // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });
};
  • lambda function を実行してデバッグ(AWSで行われる)
$ serverless invoke -f hello -l

こんな感じでレスポンス返ってきます。

{
    "statusCode": 200,
    "body": "{"message":"Go Serverless v1.0! Your function executed successfully!!","input":{}}"
}
--------------------------------------------------------------------
START RequestId: 264f962d-0808-11e7-8ff3-1f23314ea4ee Version: $LATEST
END RequestId: 264f962d-0808-11e7-8ff3-1f23314ea4ee
REPORT RequestId: 264f962d-0808-11e7-8ff3-1f23314ea4ee  Duration: 2.02 ms   Billed Duration: 100 ms     Memory Size: 1024 MB    Max Memory Used: 15 MB  
  • function の実行ログを取得
$ serverless logs -f hello -t
  • プロジェクトの削除
$ serverless remove

まとめ

予想以上にseverless flameworkが便利、
簡単にlambdaでの開発が進みそう。

phpstorm で編集→エディタのターミナルからデプロイのサイクルが
回せるのは楽だなーと。

また、lambdaってデバッグとかどうすんだろーとか
デプロイいちいちzipにしなきゃいけないのかなーとかが明らかになった。

デプロイコマンド打つとs3にzipがアップされるのでこいつを
lambda作成時に指定してやればいいのかな。

今後作りたいものは、dynamoDBとlambdaの連携とかしたいので
ローカルで開発どうすんだろーとか考えていきたい。
あと、slackからのリクエストをローカルでモックして開発とかか。
APIGateWayだっけか、そこと組み合わせるだろうから勉強しないと。。

続きを読む

serverlessでLambdaのローカル開発環境を整える

serverlessフレームワークを使ってローカル環境で作成したNode.jsをLambda関数としてデプロイ

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1212

$ brew -v
Homebrew 1.1.11
Homebrew/homebrew-core (git revision 0e1e; last commit 2017-03-11)

$ node -v && npm -v
v6.9.2
3.10.9

やったこと

何はともあれServerlessのインストール

$ npm install serverless -g

AWS CLIのインストール

$ brew install awscli
$ aws
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help
aws: error: too few arguments

AWS CLIの設定
Access Keyで設定する場合

  • 事前にIAMでグループ権限とユーザーに対するグループ追加を行う必要あり
$ aws configure
AWS Access Key ID [None]: ABCABCABCABCABCABC12
AWS Secret Access Key [None]: BCDBCDBCDBCDBCDBCDBCD+123+EFGEFGEFG45678
Default region name [None]: us-east-1
Default output format [None]: json

※AWS リージョンコード一覧
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-regions-availability-zones.html

確認

AWC CLIが使えるかの確認をします。
ここでは、EC2のインスタンス一覧表示コマンドを投げました。
(結果は何もないのでからのjsonが返ってくる。

aws ec2 describe-instances
{
    "Reservations": []
}

使ってみる

プロジェクト作成

まずはプロジェクトを作成
公式ドキュメントにある、node.jsテンプレートを使用し、プロジェクトを作成

$ serverless create --template aws-nodejs --path serverless-test
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/d_ojima/Documents/serverless-test"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  ___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.8.0
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"

それっぽいロゴが表示されます。
テンション上がりますね:watermelon:

内容を確認

$ cd serverless-test/ && tree .
.
├── handler.js
└── serverless.yml

0 directories, 2 files

デプロイ

handler.jsにサンプルが書かれている状態なので、このままデプロイしてみます。

$ serverless deploy -v
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - serverless-test-dev
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - serverless-test-dev
Serverless: Stack create finished...
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3 (583 B)...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - serverless-test-dev
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - serverless-test-dev
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionmQpsI2bHdSCO39nFrbUuIDXStzt10M9R68vwOUGdtc
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionmQpsI2bHdSCO39nFrbUuIDXStzt10M9R68vwOUGdtc
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - HelloLambdaVersionmQpsI2bHdSCO39nFrbUuIDXStzt10M9R68vwOUGdtc
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - serverless-test-dev
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - serverless-test-dev
Serverless: Stack update finished...
Service Information
service: serverless-test
stage: dev
region: us-east-1
api keys:
  None
endpoints:
  None
functions:
  hello: serverless-test-dev-hello

Stack Outputs
HelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:932608639237:function:serverless-test-dev-hello:1
ServerlessDeploymentBucketName: serverless-test-dev-serverlessdeploymentbucket-1gve57f768zkr

ブラウザからAWSコンソールを確認すると

serverlessでデプロイしたLambda関数が確認できました:airplane:
スクリーンショット 2017-03-11 18.53.10.png

また、serverlessではCloudFormationの機能を利用しているため、同時にIAMロールS3バケットなども作成されていました。

雑感

とりあえず環境構築ということで、serverlessの触り中の触りを試してみた。
今後は、外部パッケージを使ったラムダ関数の作成、API Gatewayとの連携などを試してみたい。

続きを読む

Amazon Web ServiceでJupyter notebookを立てるまでのメモ

Yet another AWS EC2 Jupyter notebook立ち上げ

ラボ内の勉強会とかのためにJupyter-notebookを使いたくて、ただ自由にできるwebサーバーをもっていなかったので、AWS EC2の無料枠で立ててみた。

AWS EC2でインスタンスの立ち上げ

ubuntuで、t2.microのインスタンスを作成します。Jupyter notebookを立ち上げる時に、ポートを8888を解放してつなげるので、以下のようにセキュリティーグループのルールを新しく作ったあげます。

スクリーンショット 2017-03-08 14.46.42.png

[参考]
http://chrisalbon.com/jupyter/run_project_jupyter_on_amazon_ec2.html

ubuntu環境の整備

sudo apt update
sudo atp upgrade
sudo apt install emacs wget pkg-config make gcc binutils

Python 環境の構築

wget https://repo.continuum.io/archive/Anaconda3-4.3.0-Linux-x86_64.sh
bash ./Anaconda3-4.3.0-Linux-x86_64.sh
## Enter/yes
source .bashrc

とりあえず立ち上げてみる

jupyter notebook --no-browser

[I 05:54:53.253 NotebookApp] Serving notebooks from local directory: /home/ubuntu
[I 05:54:53.253 NotebookApp] 0 active kernels
[I 05:54:53.253 NotebookApp] The Jupyter Notebook is running at: http://localhost:8888/?token=****
[I 05:54:53.253 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 05:54:53.254 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=****

となって、Jupyter notebookを立てることはできます。
余談ですが、[ここ|http://www.datasciencebytes.com/bytes/2015/12/18/using-jupyter-notebooks-securely-on-remote-linux-machines/] によると、localhost (Mac)で表示できるらしい、そしてやって見たらできた。

スクリーンショット 2017-03-08 14.57.46.png

ただ、毎回sshするのはめんどくさいし、public domainからアクセスした方が優しいので、いろいろ設定して行きます。

Notebook passwordの作成

公開されたdomainでnotebookを作るのはいいけどアクセスを制限するのにpasswordを設定していきます。

ubuntu@ip-172-31-27-190:~$ ipython
Python 3.6.0 |Anaconda 4.3.0 (64-bit)| (default, Dec 23 2016, 12:22:00)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from IPython.lib import passwd

In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:**********************************'

In [3]: exit

  • サーティフィケイトを作成
cd ~
mkdir .cert
cd .cert
sudo openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem
## ENTERを数回
  • Jupiter_notebook_config.pyをいじる
emacs ~/.jupyter/jupyter_notebook_config.py

## The full path to an SSL/TLS certificate file.
c.NotebookApp.certfile = '/home/ubuntu/.certs/mycert.pem'
c.NotebookApp.keyfile = '/home/ubuntu/.certs/mycert.pem'
## The IP address the notebook server will listen on.
c.NotebookApp.ip = '*'
## Whether to open in a browser after starting. The specific browser used is
#  platform dependent and determined by the python standard library `webbrowser`
#  module, unless it is overridden using the --browser (NotebookApp.browser)
#  configuration option.
c.NotebookApp.open_browser = False
## Hashed password to use for web authentication.
#
#  To generate, type in a python/IPython shell:
#
#    from notebook.auth import passwd; passwd()
#
#  The string should be of the form type:salt:hashed-password.
c.NotebookApp.password = 'sha1:********'
## The port the notebook server will listen on.
c.NotebookApp.port = 8888

ここでなぜか、sslを許可するとkernelにつながらないとかソケットが〜〜てきなエラーが大量に出てきた。どうやらこれはsafariだと出る問題らしいから、chromeでアクセス。

Jupyter notebookをたちあげていじる


ubuntu@ip-172-31-27-190:~/Notebook$ cd ~
ubuntu@ip-172-31-27-190:~/Notebook$ mkdir Notebook
ubuntu@ip-172-31-27-190:~/Notebook$ jupyter notebook
[I 06:25:19.871 NotebookApp] Serving notebooks from local directory: /home/ubuntu/Notebook
[I 06:25:19.871 NotebookApp] 0 active kernels
[I 06:25:19.871 NotebookApp] The Jupyter Notebook is running at: https://[all ip addresses on your system]:8888/
[I 06:25:19.871 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

*PUBLIC*DOMAIN*:8888にアクセスする。

スクリーンショット 2017-03-08 15.27.23.png

先ほどipython内で登録したパスワードをいれると、やっとjupyter notebookがひらけます。

スクリーンショット 2017-03-08 15.51.49.png

とりあえずなにか投げたいので、[New▼]からPython 3のNotebookを作成する。
スクリーンショット 2017-03-08 15.52.41.png

すると新しいnotebookを作成できる。これはpython用のkernelなので、pythonを全く知らない私ですが、とりあえず全世界共通言語hello worldを投げる。

スクリーンショット 2017-03-08 15.53.36.png

最高。

他の言語を使えるようにする

普段perlとRを書いているので、それぞれのkernelを入れて行きます。

まずはいろんなものを入れる

sudo apt install libzmq3-dev libmagic-dev libcairo2-dev
sudo apt install r-base libcurl4-openssl-dev libssl-dev libssh2-1-dev
  • PerlはIPerlで。
sudo apt install cpanminus
cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
cpanm Devel::IPerl
echo "export PERL5LIB=$HOME/perl5/lib/perl5" >> ~/.bashrc
source ~/.bashrc

# 以下の二つ (もしかしたらどちらか)をやらないとjupyterにkernelとして認識されない
sudo find / name -name iperl
/home/ubuntu/perl5/bin/iperl console
/home/ubuntu/perl5/bin/iperl notebook

スクリーンショット 2017-03-08 17.12.05.png

  • RはIRkernel
conda install zeromq
R

## R内
install.packages(c('repr', 'IRdisplay', 'evaluate', 'crayon', 'pbdZMQ', 'devtools', 'uuid', 'digest'))
devtools::install_github('IRkernel/IRkernel')
#相変わらずのkernel認識おまじない。
IRkernel::installspec()
##

# または
# conda install -c r r-essentials
## うまくいかないことがあるらしいからmanualの方がよいかもしれない。

そしてkernelからRを選ぶと、以下のようにRがかけます。
スクリーンショット 2017-03-08 17.21.17.png

切り替えはkernel->change kernelから

スクリーンショット 2017-03-08 17.21.01.png

もちろん他の言語も (kernelが実装されて入れば)使えます。

余談ですが、一つのpython kernelのnotebook内で複数の言語を打つ買うことができます。

pip install rpy2
#=> これだけだとlibgompがないと怒られるから、LD_LIBRARY_PATHを指定しておく。
sudo find / name -name libgomp.so.1
emacs ~/.bashrc
###
LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/home/ubuntu/anaconda3/lib:/home/ubuntu/anaconda3/pkgs/libgcc-4.8.5-2/lib;
export LD_LIBRARY_PATH
###

#=> こうするとreadlineがおかしいといわれるから、readlineをちょっと変える
# [参考] https://github.com/ContinuumIO/anaconda-issues/issues/152#issuecomment-225214743

conda remove --force readline
pip install readline.

とするとおなじnotebook内でいろんな言語をかけるようになりました。めでたし。
スクリーンショット 2017-03-09 15.30.47.png

いろんなlibrary/module入れる

wget -O g-language-1.9.1.tar.gz "https://ja.osdn.net/frs/redir.php?m=jaist&f=%2Fglang%2F64267%2Fg-language-1.9.1.tar.gz"
sudo apt install gnuplot imagemagick libgd-dev
cpanm --force --verbose Chart::Graph
>> gnuplot
cpanm ./g-language-1.9.1.tar.gz
  • Rのいろいろ
## conda install -c r r-essentialsするといろんな事件が起きるのでオススメしない。
conda install -c r r-ggplot2
conda install -c r r-reshape

余談

jupyter notebookでperl kernel使ってる時に、pngとかをinlineで表示したい時があると思います。
そういうときは。

IPerl->png( "http://www.libpng.org/pub/png/PngSuite/ccwn3p08.png" );
# もしくは
IPerl->png( "graph/ecoli.png" );

といったふうに、相対パスでperl内で出力したpngなどを表示できます。

続きを読む

Cyberduckを使ってAWS S3にファイルアップロードを行う手順(Mac編)

説明用に、ファイルアップロードを行う手順のみをまとめました。

前提

S3へのアップロードが可能な
* アクセスキーID
* シークレットアクセスキー
が手元にある

1. Cyberduckをダウンロード

https://cyberduck.io/index.ja.html?l=ja

2. 接続先設定を行う

image

「新規接続」 から
* 最上部のプルダウンは「S3(Amazon シンプルストレージサービス)」を選択
* 「アクセスキーID」
* 「シークレットアクセスキー」
を設定して「接続」をクリック

以下のような画面が表示されれば接続成功。
ここにファイルをドラッグアンドドロップすればファイルアップロードができる。

image

3. ブックマークとして保存

2回目以降はすぐに接続できるように、
「アクション」(歯車のアイコン) → 「新規ブックマーク」
でブックマークとして保存する。
わかりやすいように「ニックネーム」には任意の名称をつけておくと良い。

image

続きを読む

macOS SierraでAWS CLIインストール時にエラー(Found existing installation: six 1.4.1)

結論、以下のコマンドでインストールできる

sudo pip install awscli --upgrade --ignore-installed six

以下、経緯

AWS CLIをインストールしたい

  • ここを見てインストールをすすめた
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
sudo python get-pip.py
sudo pip install awscli

謎のエラー

Found existing installation: six 1.4.1
    DEPRECATION: Uninstalling a distutils installed project (six) has been deprecated and will be removed in a future version. This is due to the fact that uninstalling a distutils project will only partially uninstall the project.
    Uninstalling six-1.4.1:
Exception:
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 342, in run
    prefix=options.prefix_path,
  File "/Library/Python/2.7/site-packages/pip/req/req_set.py", line 778, in install
    requirement.uninstall(auto_confirm=True)
  File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 754, in uninstall
    paths_to_remove.remove(auto_confirm)
  File "/Library/Python/2.7/site-packages/pip/req/req_uninstall.py", line 115, in remove
    renames(path, new_path)
  File "/Library/Python/2.7/site-packages/pip/utils/__init__.py", line 267, in renames
    shutil.move(old, new)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 302, in move
    copy2(src, real_dst)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 131, in copy2
    copystat(src, dst)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 103, in copystat
    os.chflags(dst, st.st_flags)
OSError: [Errno 1] Operation not permitted: '/tmp/pip-Rj2bkf-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six-1.4.1-py2.7.egg-info'

エラーを見てみた

Found existing installation: six 1.4.1
(既存のインストールが見つかりました)
  • sixとかいうのが入っているらしい
  • six:python2系と3系の差異を埋めてくれるユーティリティライブラリ

すでにいろんな人が書いてた

続きを読む

git-secretsをSourceTree (Macintosh)で使えるようにする手順

背景

目的

この辺にあるように秘密情報のGitプッシュ・公開を防ぐために、git-secrets (https://github.com/awslabs/git-secrets) を導入したときのことです。

課題

git-secrets をインストール後に、SourceTreeでプッシュしようとすると、エラーを吐くようになりました。

git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree commit -q -F /var/folders/xn/1hl03gp55_3df0y1xl37tg900000gp/T/SourceTreeTemp.xNvMuf 
git: 'secrets' is not a git command. See 'git --help'.
Completed with errors, see above

どうやら「クラウド破産しないように git-secrets を使う」の「SourceTreeなどを使っているなら」部分の設定ができていない様子。

今回の主題

タイトルのとおりですが、git-secrets導入に際して、SourceTreeでGitを使い続けるための具体的な手順をまとめておきます。

環境条件

  • macOS Sierra version 10.12.3
  • SourceTree version 2.3.1
  • Git version 2.10.1 (Apple Git-78)

手順概要

  1. MacintoshのGitコマンドのファイルディレクトリに git-secrets をリンクする
  2. SourceTreeが利用するGitを「システムのGit」を使用するに変更する

概要と書くとこうなるのですが、意外に付帯する作業があったので、書き出していきます。

設定

[手順1] MacintoshのGitコマンドのファイルディレクトリに git-secrets をリンクする

Gitの場所を確認

git の場所を確認しておく -> /usr/bin/git

$ which git
/usr/bin/git

つまり、/usr/bin/git-secrets をリンクすると良いことになります。

git-secretsの場所を確認

git-secrets の場所を確認しておく -> /usr/local/Cellar/git-secrets/1.2.1/bin/git-secrets

$ which git-secrets
/usr/local/bin/git-secrets
$ readlink git-secrets
/usr/local/Cellar/git-secrets/1.2.1/bin/git-secrets

あとは、

cd /usr/bin
sudo ln -s /usr/local/Cellar/git-secrets/1.2.1/bin/git-secrets

で、終了かと思いきや、/usr/local/usr/bin へのリンクはsudo しても拒否されてしまいます。ですので、準備はまだまだ続きます。

System Integrity Protecton(SIP)を無効にする

El Capitan以降のOSでSystem Integrity Protecton(SIP)という機能が追加されセキュリティが強化されたとのことで、これを一旦無効にしてあげる必要があります。

  1. command + r を押したままでMacを起動させ、リカバリーモードで立ち上げる
  2. ヘッダメニューの「ユーティリティ」から「ターミナル」を立ち上げる
  3. ターミナルでSIPコマンド csrutil disable を打つ

git-secretsを/usr/bin/にリンクする

SIPが無効化されたら、いよいよgit-secrets を/usr/bin/にリンクします。

cd /usr/bin
sudo ln -s /usr/local/Cellar/git-secrets/1.2.1/bin/git-secrets

System Integrity Protecton(SIP)を有効にする

目的のリンクがはれたら、SIPを有効にし直します。

  1. command + r を押したままでMacを起動させ、リカバリーモードで立ち上げる
  2. ヘッダメニューの「ユーティリティ」から「ターミナル」を立ち上げる
  3. ターミナルでSIPコマンド csrutil enable を打つ

[手順2] SourceTreeが利用するGitを「システムのGit」を使用するに変更する

システムのGitを選択する

「SourceTree」の「環境設定」を開きます。更に「Git」タブを選択します。
スクリーンショット_2017-02-07_14_44_59.png

「システムのGitを使用する」をクリックして、git選択画面にいきます。 
スクリーンショット_2017-02-07_14_45_36.png

/usr/bingit を選択し、「開く」をクリックします。ここで、同じ階層に先程リンクしたgit-secrets も確認できます。

環境設定の画面に戻るとシステムのGitが選択されていることがわかります。

スクリーンショット_2017-02-07_14_45_41.png

これで、Gitをプッシュし直すとエラー無しでプッシュすることが出来ました。

まとめ

ただリンクするにも意外とやることがあったので、簡単にまとめてみました。

続きを読む

AWS CLI での備忘録

AWS コマンドラインインターフェイスは基本コンソールでGUI操作するって人も知っておくとかなり便利です。
私がよく使うコマンドを備忘録がわりに投稿します。
ちなみに、今は開発者プレビューですが、オートコンプリートとかをしてくれるaws-shellってのも出てます。

基本設定

AWS-Cliのインストール(Mac)

pip install awscli

AWS-CliにはPython 2.6.5 以降が必要です。
pythonが入っていない場合(Macはプリインストールされてるはずなので、ないとは思いますが、、)
Python.org/downloadsから落とすか、下記を実行

python --version  # これで2.6.5以上であればOK
brew install python # homebrew入ってればこれでインストールできる

pipが入っていない場合は、

python get-pip.py

AWS-Cli設定

下記のAccess KeyとSecret Access KeyはIAMの[認証情報] > [アクセスキー]から作成する

$ aws configure
Access Key ID: XXXX
Secret Access Key: XXXX 
region: ap-northeast-1 # 自分が主に使っているリージョンを設定

S3操作

S3でよく使うのは下記

バケット一覧表示

$ aws s3 ls

ローカルとS3とのファイル操作

aws s3 cp . s3://hoge/ --recursive  # localのhoge_localというdirectoryをhogeというバケットに全部アップロードする場合
aws s3 cp s3://hoge/ ./hoge_local --recursive # localのcurrent directoryにhogeというバケットの中身を全部コピーする場合

ローカルとの同期

$ aws s3 sync hoge_local/ s3://hoge/ --delete # localのhoge_localというdirectoryをhogeというバケットを同期

ファイル削除

$ aws s3 rm s3://hoge/ --recursive  # hogeというバケットを削除

続きを読む

AWS Lambda上でOCRして文字の位置を特定したい人生だった。

やりたいこと

  • OCRを使って文字の位置を検出したい
  • そんなに頻繁に使うものじゃないからLambdaで動かしたい
  • Webから使いたい

というわけで、できましたー

文字位置特定 with OCR on AWS Lambda

リポジトリはこちら

tesseractってなに?

  • OCRを行ってくれるソフトウェア
  • Macにはbrewで入る(v3.04)
  • 文字を取得するだけじゃなくて文字の位置をhOCR(html)やtsv形式で出力できる <- 重要

どうやってLambdaで動かすの?

  • StackOverflowを参考に…
  • Lambdaではスタンドアローンなバイナリファイルや.soをちゃんと耳そろえてアップすれば動く
  • subprocess(Pythonのコマンドライン実行ライブラリ)も動く

つまり…!!
tesseractと一緒にアップすればLambdaでOCRが動く!!

ちなみに、AmazonLinux上でビルドしないとPillow(PIL)がELF headerがないとかいう妖精さんの首がもげる現象に立ち会い無事死ねます。

文字列の位置どうやって検出するの?

  • 一般的なOCRでは文字をテキストで返してくれることがほとんど
  • Docを読むとv3.05ではtsv形式がサポートされてるくさい
  • 普通にインスコするとtesseract(v3.04)が入っちゃう
  • v3.05を使うべくStackOverflowのとおりに手でビルドしないといけない

これはつらかった。

というわけでいい加減、どうやって導入したかかきます。

 インストール

全部ec2-userでいいです。

必要なパッケージのインストール

sudo yum install -y gcc gcc-c++ make
sudo yum install -y autoconf aclocal automake
sudo yum install -y libtool
sudo yum install -y libjpeg-devel libpng-devel libtiff-devel zlib-devel
sudo yum install -y git

nvmのインストール

AmazonLinuxではyumでいれたnodeのバージョンが古すぎて色々(後述)つらいのでnvmいれておきます。
とはいえAmazonLinuxじゃないとビルドしたところでLambdaでエラーはいてしまうので頑張りましょう。

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash
$ source ~/.bashrc 

$ nvm install v6.9.4  
$ nvm alias default v6.9.4  

# バージョンを確認
$ npm -v
$ node -v

Leptonicaのインストール

Leptonica is 画像解析とかやってくれるOSSでtesseract動かすのに必要
ここのバージョンをあげないとtesseractのv3.05も使えない

$ cd ~
$ mkdir leptonica
$ cd leptonica

$ wget http://www.leptonica.com/source/leptonica-1.74.tar.gz

# unzip
$ tar -zxvf leptonica-1.73.tar.gz
$ cd leptonica-1.73

# build
$ ./configure
$ make
$ sudo make install

Tesseractのインストール

まだv3.05はdevなのでリリースに乗ってない == zipが落ちてないのでcloneして頑張ります。

$ cd ~
$ git clone https://github.com/tesseract-ocr/tesseract.git
$ cd tesseract/
$ git checkout -b 3.05 origin/3.05

# initialize
$ ./autogen.sh

# build
$ ./configure
$ make
$ sudo make install

Lambda用にパッケージング

$ cd ~
$ mkdir package
$ cd package

# Copy libraries
$ cp /usr/local/bin/tesseract .
$ mkdir lib
$ cd lib
$ cp /usr/local/lib/libtesseract.so.3 .
$ cp /usr/local/lib/liblept.so.5 .
$ cp /lib64/librt.so.1 .
$ cp /lib64/libz.so.1 .
$ cp /usr/lib64/libpng12.so.0 .
$ cp /usr/lib64/libjpeg.so.62 .
$ cp /usr/lib64/libtiff.so.5 .
$ cp /lib64/libpthread.so.0 .
$ cp /usr/lib64/libstdc++.so.6 .
$ cp /lib64/libm.so.6 .
$ cp /lib64/libgcc_s.so.1 .
$ cp /lib64/libc.so.6 .
$ cp /lib64/ld-linux-x86-64.so.2 .
$ cp /usr/lib64/libjbig.so.2.0 .

# Get trained data
$ cd ..
$ mkdir tessdata
$ cd tessdata
$ wget https://github.com/tesseract-ocr/tessdata/raw/master/eng.traineddata
$ wget https://github.com/tesseract-ocr/tessdata/raw/master/osd.traineddata

# Make config file
$ mkdir configs
$ echo 'tessedit_create_tsv 1' > tsv

$ cd ../..
$ zip -r package.zip package

これでLambdaのパッケージに package を閉じ込めてあげると使えるようになります!

やってみた結果wwwwww

草すみませんでした。

image.png

こんな画像をあげた結果がこれ

level   page_num    block_num   par_num line_num    word_num    left    top width   height  conf    text
1   1   0   0   0   0   0   0   1080    1920    -1  
2   1   1   0   0   0   29  11  1025    50  -1  
3   1   1   1   0   0   29  11  1025    50  -1  
4   1   1   1   1   0   29  11  1025    50  -1  
5   1   1   1   1   1   29  11  548 50  60  GnAflQflAA
5   1   1   1   1   2   640 15  167 43  58  X-IIZII"
5   1   1   1   1   3   899 14  155 44  89  l11:57
2   1   2   0   0   0   0   0   1080    76  -1  
3   1   2   1   0   0   0   0   1080    76  -1  
4   1   2   1   1   0   0   0   1080    76  -1  
5   1   2   1   1   1   0   0   1080    76  95   
2   1   3   0   0   0   192 829 197 66  -1  
3   1   3   1   0   0   192 829 197 66  -1  
4   1   3   1   1   0   192 829 197 66  -1  
5   1   3   1   1   1   192 851 93  44  87  00
5   1   3   1   1   2   336 829 53  66  71  la
2   1   4   0   0   0   122 992 718 109 -1  
3   1   4   1   0   0   122 992 718 109 -1  
4   1   4   1   1   0   122 992 718 47  -1  
5   1   4   1   1   1   122 995 88  44  89  Sign
5   1   4   1   1   2   229 995 31  34  94  in
5   1   4   1   1   3   276 997 40  32  86  to
5   1   4   1   1   4   332 997 64  42  89  get
5   1   4   1   1   5   410 993 66  36  86  the
5   1   4   1   1   6   493 997 104 32  84  most
5   1   4   1   1   7   613 997 66  32  86  out
5   1   4   1   1   8   695 992 41  37  91  of
5   1   4   1   1   9   749 1003    91  36  93  your
4   1   4   1   2   0   122 1065    144 36  -1  
5   1   4   1   2   1   122 1065    144 36  87  device.
2   1   5   0   0   0   124 1269    312 46  -1  
3   1   5   1   0   0   124 1269    312 46  -1  
4   1   5   1   1   0   124 1269    312 46  -1  
5   1   5   1   1   1   124 1269    111 36  87  Email
5   1   5   1   1   2   253 1279    40  26  92  or
5   1   5   1   1   3   310 1269    126 46  89  phone

ソースはこんなん

import requirements

from PIL import Image
import sys
import pyocr
import pyocr.builders

import urllib
import os
import subprocess
import base64
import json
import boto3

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.join(SCRIPT_DIR, 'lib')
LANG_DIR = os.path.join(SCRIPT_DIR, 'tessdata')

def response(code, body):
    return {
        'statusCode': code,
        'headers': {
            'Access-Control-Allow-Origin': '*',
        },
        'body': json.dumps(body),
    }

def handler(event, context):
    # Get the bucket and object from the event
    try:
        tools = pyocr.get_available_tools()
        if len(tools) == 0:
            print("No OCR tool found")
            sys.exit(1)
        tool = tools[0]
        print("Will use tool '%s'" % (tool.get_name()))

        request = event['body']

        result_filepath = '/tmp/result'
        img_filepath = '/tmp/image.png'
        with open(img_filepath, 'wb') as fh:
            fh.write(base64.decodestring(request['template']))

        command = 'LD_LIBRARY={} TESSDATA_PREFIX={} {}/tesseract {} {} -l eng --oem 0  tsv'.format(
            LIB_DIR,
            SCRIPT_DIR,
            SCRIPT_DIR,
            img_filepath,
            result_filepath
        )
        print command

        try:
            output = subprocess.check_output(
                command,
                shell=True,
                stderr=subprocess.STDOUT
            )
            print(output)

            with open(result_filepath + '.tsv', 'rb') as fh:
                print(fh.read())
        except subprocess.CalledProcessError as e:
            return "except:: " + e.output

    except Exception as e:
        print(e)
        raise e

あとはGitHub上のserverless.ymlなり何なりを書き換えてご自由にお使いくださいませー。

続きを読む

Docker+Grafanaでアカウントを横断してCloudWatchを可視化する

ちょっとしたモニタリングだったらCloudWatchでも十分。
ただ、普段コマンドラインツールで操作していることもあるし、複数アカウントを持っていたりするのでマネージメントコンソールだと使い勝手が悪い。
そんな悩みをGrafanaが解決してくれたので自分用にメモメモ。

必要なもの

  • AWSのIAM User
  • aws-cli
  • Docker for Mac(Docker Machineでも可)

credentialsの登録

自分が普段使っているMacでは、aws-cliを使ってprofileをいくつも登録してある。
登録するときはこんな感じ。
profile名は適宜変更すること。
すでに作成済みの場合は実施不要。

$ aws configure --profile hogehoge
AWS Access Key ID [None]: aaaaa
AWS Secret Access Key [None]: bbbbb
Default region name [None]:
Default output format [None]:

すると、以下の感じで必要な情報が登録されているはず。

$ cat ~/.aws/credentials
[hogehoge]
aws_access_key_id = aaaaa
aws_secret_access_key = bbbbb

credentialの取り扱いには気をつけること!

DockerでGrafanaを起動

上記で作成したcredentialsを-vオプションでGrafanaコンテナに渡す。
公式イメージあるので捗る。
Grafanaは3000ポートでListenしているのでそれもあわせてマッピング。

$ docker run -d -p 3000:3000 -v ~/.aws/credentials:/usr/share/grafana/.aws/credentials --name grafana grafana/grafana
3d7de10094f1d84dbedd8a77fb55ef5c997ccdde31722a114bcd25388b1a8b3d

起動した。

Grafanaにデータを追加

接続してみる。

$ open http://localhost:3000

screencapture-localhost-3000-login-1484041461957.png

デフォルトのログインID/PWはadmin/admin
ログインするとこんな感じ。
Kobito.cKv8Tt.png
なんか前見たときよりUIがよくなってるかも。
ちょっと目立つ感じになってるAdd data sourceボタンを押す。

Kobito.b6Dvv3.png
こんな画面になる。
Nameには任意のData Sourceの名前をつけてる。
TypeのプルダウンからCloudWatchを選択。
Auth ProviderはCredentials file以外にもAccess & secret keyやARNが選択できるが、変更せずにCredentials fileを指定する。
Default Regionは適宜選択すること。
Custom Metrics namespaceはなにかあれば入力するが、とりあえず空のままでOK。
左下のAddボタンを押して、Successと表示されれば登録できてるっぽい。

Kobito.KIPEF2.png
こんな感じで登録できた。

あとはdashboardでポチポチグラフを追加していい感じの画面を作ればOK。
Kobito.TV43uj.png


Dockerで起動しているのでこのままだとデータの永続化とかはできてないけど、とりあえず簡単に起動できて便利。

続きを読む