【Slack】新しいチャンネルが作成されたら通知できるようにしてみた!

社内でもSlackを導入しているのですが
新しいチャンネルが作成されても気づくことができず
後にこんなチャンネルがあったのか!?
ということがしばしばあったので
新しいチャンネルが作成されたら通知する仕組みを作ってみました😊

作成した構成


プログラムを書いてそれをサーバに配置しておくというパターンではなく
Slack Appを使用し、さらにサーバレスで実装してみました!

f:id:aym413:20170816152659p:plain

API GatewayとLambdaの設定


API Gateway
* メソッドは「POST」
* 統合リクエストの「統合タイプ」は「Lambda関数」を設定

Lambda
* 言語は「Node.js 6.10」
* Slack Appとの連携確認が必要なため、一旦下記のコードで作成

exports.handler = (event, context, callback) => {
    context.succeed(event["body-json"]);
};


⑵Slack Appを作成


下記URLにアクセスし、「Start Building」をクリック
https://api.slack.com/

「App Name」と「Development Slack Team」を入力し、「Create App」をクリックすると… f:id:aym413:20170816153143j:plain

アプリケーションが作成されました!

⑶Slack Appの設定 −その1− Bot User


続けてアプリケーションの設定をしていきます

メニューから「Bot Users」を選択
f:id:aym413:20170816155022j:plain

「Default username」にBotのユーザ名を入力

Botをリアルタイムに処理させるため
「Always Show My Bot as Online」を「On」にする

f:id:aym413:20170816163111j:plain

最後に「Add Bot User」をクリックして保存します

⑷Slack Appの設定 −その2− Event Subscriptions


メニューから「Event Subscriptions」を選択
f:id:aym413:20170816154958j:plain

「Enable Events」を「On」にして
「Request URL」に⑴API GatewayとLambdaを設定するで作成した
API Gatewayのエンドポイントを入力します
しばらくして「Verified」になればOKです!
f:id:aym413:20170816155417j:plain

ここで「Verified」にならなければLambdaのコードか
API Gatewayの設定にミスがあるかもしれませんーーー😥

少し下にいって「Subscribe to Bot Events」に
「channel_created」のイベントを追加します
f:id:aym413:20170816155636j:plain

最後に「Save Changes」をクリックして保存します

⑸Slack Appの設定 −その3− Install App


メニューから「Install App」を選択
f:id:aym413:20170816160142j:plain

「Install App to Team」をクリック!
f:id:aym413:20170816160139j:plain

アプリケーションインストールの確認画面が表示されるので
問題なければ「Authorize」をクリックします
f:id:aym413:20170816160603j:plain

インストールされるとSlackの画面で
アプリケーションが起動しているのを確認できます
f:id:aym413:20170816160822j:plain

⑹プログラムの作成


作成された新しいチャンネルを通知するコードを書いていきますー

その前に…Botのtokenが必要なのでそれをメモしておきます
メニューから「OAuth & Permissions」を選択して
f:id:aym413:20170816161208j:plain

Bot User OAuth Access Token」に書かれているtokenをメモメモ。。
f:id:aym413:20170816161202j:plain

いよいよコードの作成!
今回はBotkitを使って作成しました
Botkitのインストール方法はこちらの記事を参考にさせていただきました!
http://blog.duck8823.com/entry/2016/05/20/005734

コードはいたってシンプル↓

# vi index.js
//slack settings
var Botkit = require('botkit');
var controller = Botkit.slackbot({
  debug: true
});

var bot = controller.spawn({
    token: <メモしたBotのtoken>
});

// slack new channnel
exports.handler = (event, context, callback) => {
  var channelName = event["body-json"]["event"]["channel"]["name"]
  bot.say({
    text: 'new channel: #' + channelName,
    link_names: 1,
    channel: 'C2XXXX' //通知するチャンネルID
  });
};

作成したコードをzipにします

# zip -r xxxx.zip index.js node_modules

zipファイルをLambdaにアップロードすれば完了です!

⑺新しいチャンネルを作成すると通知されるか確認


早速動作するか確認しましょう
f:id:aym413:20170816162241j:plain

おっ!無事に新しいチャンネルの通知が来ました〜
f:id:aym413:20170816162238j:plain


感想


今回作成したものはPublicチャンネルのみ通知されます
もともとPrivateチャンネルは通知されないみたいです
Botのアクションをトリガーにして
他にも様々な仕掛けを作ることができそうです🤗

JAWS DAYS 2017で登壇してきました!

先週3/11(土)JAWS DAYS 2017が開催されました〜
 
昨年はボランティアスタッフとして参加しましたが
今回はスピーカーとして参加してきました😄
 
 
登壇に至った経緯

今回JAWS DAYSのテーマは「Link Up!」
 
私自身、最初はコミュニティが好きではなくて
社内は外部とのコミュニケーションをとる人も少ない環境でした。
そこから色々なことを経て、多くの人と繋がることができたことは
今の私にとってとても大きな価値になっています。
きっと同じような環境にいる人、悩んでいる人もいるんじゃないかなと。
私の経験談が誰かの役に立てれば、、そんな思いで公募セッションに応募させてもらいました。
 
応募者は20名ほどいたようです!!
そんな中選んでいただいてありがとうございます!!
 
 
登壇してみて

正直、全然聞いてくれる人は少ないかも。。と思っていましたが、なんと満席!!
 

f:id:aym413:20170319234257j:image

 
聞いてくださった方本当にありがとうございました😭😭
 
緊張しすぎて日本語ハチャメチャ、時間がかなり早く終わってしまったなど
色々反省点はありました。。
それでも終わった後に「良かったです」と話しかけていただいたり、
Twitterでも「若手エンジニアに聞かせたい」などの反応をいただきとても嬉しいです!
 
みなさんに「一歩踏み出そう!」というメッセージを伝えたので
私も今年は一歩進んでAWS HUBに参加してみようかなと思います!!
 
セッション資料はこちらです↓
 


 
【追記】懇親会の司会もしました!

お誘いいただき、懇親会の司会もやることに〜
 
司会なんてやったことないし、どうなるかと思っていましたが
みんなお酒が入っていたのでなんとかなりましたw
 
コスプレしていたので、色んな方と写真も撮って
覚えていただくきっかけになったのではないかなと思います😉
 
 
やっぱり色んな人と交流するには、人前に出るのが一番いいですね!
今年のJAWS DAYSは登壇や司会を通じて、
新しい経験と仲間のつながりを増やすことができ
私自身一歩踏み出せたイベントでした😊✨
 

VPC内からLambdaを実行する際のハマりどころ

VPC内のLambdaからEC2 Run Commandを実行しようとしたら、下記のエラーが出ました

Request has been terminated Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.

また、ログを確認すると、時間めいいっぱい使っている様子

Task timed out after 300.00 seconds.

試しにマネジメントコンソールから実行すると、即「Success」が返ってきたので 権限周りやコードに問題はなさそう…

しばらくして気が付きました

Lambdaがプライベートサブネット内にいる!

つまり、LambdaがEC2 Run Commandを実行する際に インターネットに接続できる環境でないとダメ!!

ということで、この場合はパブリックサブネットに NATサーバ or NAT Gatewayを立てれば問題なしでした^^

というか、サブネットの選択を間違えたかな。。 この場合はパブリックサブネットにLambdaを置くのがベストプラクティスになるのでしょうかー

【JAWS-UG CLI】 #64 ALB入門 に参加しました!

9/26(月)に開催されたJAWS-UGのCLI支部に久々に参加してきました!
 
ALB気になっていたのですが、案件でもまだ使用する予定もなかったのでとてもいい機会でしたー
また、AWSの中の方にも来ていただき、有益な情報も聞けました!
 
ハンズオンの資料はこちらです!
 
ALBの概要を簡単に。
・パスベースのルーティングが可能
・アクセスされるURLパスごとに優先度を分けることができる(優先度のルールは10個まで設定可能)
 ルールの値が小さい順に評価され、最初に合致した値が適用されます
・http/httpsのみ対応
・ターゲットにS3を設定することはできない
AWS内でテストした結果では、CLBよりALBの方が安くなる(ALB推奨らしい)
・過剰なアクセスがある場合は、CLB同様プレウォーミングの申請は必要
・EC2同様、削除防止機能がある
・価格設定がやや複雑(詳細は以下に記載)
・CLBからALBに移行する際の移行ツールがある(https://github.com/aws/elastic-load-balancing-tools
・ALBを削除するとリスナーなども一緒に削除される
 ※ターゲットグループは別途削除が必要
 

 
価格については、以下の2つの料金の合算する形となっています。
・1時間あたりの料金(CLBに較べて10%引き)
・LCU時間あたりの料金
 LCU…「Load Balancer Capacity Units」の略でALBの使用量の単位
 
「LCU時間あたりの料金」とは?
LCUは、下記3つの指標を計測して、最も高いものを基準に課金されるようです。
・1秒あたりの新規コネクション数
・1分アクティブなコネクション数
・データ転送量
 
1LCUには、下記のいずれかの内容が含まれてます。
・2 KBの証明書の場合: 25 接続/秒、3000アクティブ接続、2.22 Mbpsのデータ転送
・4 KBの証明書の場合: 5 接続/秒、3000アクティブ接続、2.22 Mbpsのデータ転送
 
Q. AWS ACMの証明書を使った場合はどうなる?
AWS ACMを使用した場合は、2KBの証明書を使用したのと同等になるそうです。(AWSの中の人からの回答)
 
 
次回のCLI支部は祝日スペシャルです!
 
 
 

Lambdaで最新AMIを取得する!(Python)

Lambda(python)で最新AMI IDを取得するプログラムを書きました。

Windowsは「Windows Servier 2012 R2 Base」、Linuxは「Amazon Linux」の最新AMI IDを取得してます。 Filters部分をカスタマイズしてもらえれば、その他にも使えると思います!    

Windows

import boto3

def lambda_handler(event, context):
    client = boto3.client('ec2')
    response = client.describe_images(
        Owners=['amazon'],
        Filters=[
            {
                'Name': 'root-device-type',
                'Values': ['ebs']
            },
            {
                'Name': 'architecture',
                'Values': ['x86_64']
            },
            {
                'Name': 'name',
                'Values': ['Windows_Server-2012-R2_RTM-Japanese-64Bit-Base*']
            }
        ]
    )
    
    list = []
    
    for x in response["Images"]:
        name = x["Name"]
        ami_id = x["ImageId"]
        list.append([name, ami_id])
    
    list.sort(key=lambda x:x[0], reverse=True)
    print list[0][1]

Linux

import boto3

def lambda_handler(event, context):
    client = boto3.client('ec2')
    response = client.describe_images(
        Owners=['amazon'],
        Filters=[
            {
               'Name': 'root-device-type',
                'Values': ['ebs']
            },
            {
                'Name': 'architecture',
                'Values': ['x86_64']
            },
            {
                'Name': 'block-device-mapping.volume-type',
                'Values': ['standard']
            },
            {
                 'Name': 'name',
                 'Values': ['amzn-ami-hvm*']
            }
        ]
    )
    
    list = []
    
    for x in response["Images"]:
        name = x["Name"]
        ami_id = x["ImageId"]
        list.append([name, ami_id])
    
    list.sort(key=lambda x:x[0], reverse=True)
    print list[0][1]

【備忘録】CloudWatchLogsのロググループ作成とログ保持期間を変更するワンライナー

以前、【備忘録】CloudWatchLogsのログ保持期間を変更するワンライナーを投稿しましたが、 今回は、少しバージョンアップして、CloudWatchLogsのロググループ作成とログ保持期間を変更するワンライナーです!

for LOGGROUPNAME in $(cat <CloudWatchLogsのロググループ名を入れたファイル>) ;do aws logs create-log-group --region ap-northeast-1 --log-group-name ${LOGGROUPNAME} && aws logs put-retention-policy --region ap-northeast-1 --log-group-name ${LOGGROUPNAME} --retention-in-days <ログ保持期間>;done

※事前に<CloudWatchLogsのロググループ名を入れたファイル>を作成しておいてください!

【備忘録】CloudWatchLogsのログ保持期間を変更するワンライナー

CloudWatchLogsのログ保持期間を変更するワンライナーです。

aws logs describe-log-groups --region ap-northeast-1 --query 'logGroups[].logGroupName' --output text| tr '¥t' '¥n' | while read LOGGROUP; do aws logs put-retention-policy --region ap-northeast-1 --log-group-name ${LOGGROUP} --retention-in-days 7; done

ロググループが50個ほどあったので楽チンに変更できました(°∀° )/