AWS cloudwatchlogsのサブスクリプションフィルターのlambdaテスト
AWSのcloudwatchlogsのサブスクリプションフィルターから呼び出されるlambdaをテストするときにやりにくかったのでメモ。
- 本家マニュアルのお言葉
サブスクリプションフィルタを介して宛先サービスに送信されるログは、Base64 でエンコードされ、gzip 形式で圧縮されます。
- lambdaでテストするときに出てくるcloudwatchlogsの形式
{ "awslogs": { "data": "BASE64ENCODED_GZIP_COMPRESSED_DATA" } }
gzipした後にbase64でエンコーディングする。messageの箇所にエラーメッセージを入れる。
require 'base64' require 'zlib' str = <<JSON {"messageType":"DATA_MESSAGE","owner":"123456789123","logGroup":"testLogGroup","logStream":"testLogStream","subscriptionFilters":["testFilter"],"logEvents":[{"id":"eventId1","timestamp":1440442987000,"message":"hogehogeエラーメッセージ"}]} JSON # gzip作成 Zlib::GzipWriter.open('./gzip/gzip.gz') {|gz| gz.write str } # base64でエンコード cloudwatchlogs_params = Base64.encode64(File.read('./gzip/gzip.gz')) p cloudwatchlogs_params
- dataに標準出力された値を入力してテストデータを作成
{ "awslogs": { "data": "H4sIAJTHuWAAA0VPOwrCQBDtPcbUKRJdjdoFjCJoFTsRiTrEhSQbdldFgk32\nJHZ6A0FvsxdxEhWLgffjzUwJGSoVJ7g4FwhDGAWLYD0PoyiYhOCAOOUoSfba\nHdbt+f0BAZJTkUykOBTkaFR69qONE2mJcfa3vtwBddioreSF5iIf81SjVDBc\nNrEPhVVTEB4x17VVAt9RD9Z8uvOoQnM6V8cZbfYYcxlrD/q+67rO7w2K70WC\n9djqZs3dmpc1V2uMrZ41rh5wWV1ab4fCX2T4AAAA\n" } }
eclipse
- 基本設定
// コメントの日本語が文字化け 一般 > 外観 > 色とフォント > テキストフォント > 日本語に対応したフォント(MS ゴシックなど) // タブ・空白を表示 一般 > エディター > テキストエディター > 空白文字を表示にチェック // gitの差分表示 ウィンドウ > 一般 > エディタ > テキストエディター > クイックDiffで使用する参照ソースを「Gitリヒビジョン」に変更。 // 保存時にフォーマットを適用 設定 > Java > エディター > 保管アクション
- 文字化け対応
ワークスペースで文字コードをutf-8に設定してもeclipseがshif-jisで勝手に解釈してくれるので文字化けしてしまう場合の対応 eclipse.iniに「-Duser.language=en」を追記する。
dockerコンテナからhostにリクエストできるようにする
dokcer-composeでアプリを立ち上げていましたが、外部サービスにアクセスする処理にスタブサーバーを使いたかったので対応しました。docker-composeに組み込んでもいいのですが、それをやるほどではなかったので組み込まなかったです。
- docker host内でプライベートIPアドレスを取得
ifconfigなどを使用してプライベートIPアドレスを取得しておく
- docker_compose.ymlに追記
ホストにリクエストしたいコンテナの設定に下記の設定を追記する。
extra_hosts: - "stub_server:取得したプライベートIPアドレス"
- 実行確認
コンテナ内でcurl stub_server:8000/getのようにして実行確認を行う。
extra_hostsはコンテナの /etc/hosts ファイルにホストを追加する設定です。ホストからコンテナのリクエストの設定なのでportの設定を「8080:8000」のようにしただけだと通信できませんでした。またhost.docker.internalというDNS名も用意されていますが、これはDocker Desktop For Mac/Windowsの設定なのでWSLで起動しているdockerには効きませんでした。
https://docs.docker.jp/compose/compose-file.html#extra-hosts
Javascript/Date.toJSON
日付をJavascriptで取得してサーバーにリクエストしたときに日付がずれてしまったので、その対応。原因はtoJSONメソッドを呼ぶとUTCに変換されてしまうため。そのため日付にJST分足して対応した。下記の例は2020-11-25日に実行。
const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()) console.log(today.toJSON()); today.setHours(today.getHours() + 9) console.log(today.toJSON()); # 出力結果 > "2020-11-24T15:00:00.000Z" > "2020-11-25T00:00:00.000Z"
Pseudo-terminal will not be allocated because stdin is not a terminal
デプロイタスクを書いていたらエラーが発生しました。sshを多段階で実行したら最後に実行した箇所で端末が割り当てられないのが原因だそうです。-tオプションを付ければいいのですが、実行してもうまくいかないことがあります。その場合は-tオプションを重ねると強制的に端末が割り振られます。
ssh -t -t user@host command
jenkins/pipeline
最低限動かすのに必要なスクリプトのメモ。 cronの設定やビルド数の制御などもjenkinsファイルにそのまま書いたほうがGUIで入力しなくて済むしポータブル。 postセクションの「failure」は失敗したときのみ実行される。「cleanup 」はステップの成否にかかわらず実行される。 失敗したら一部だけリトライ処理をしたいときはscriptをそのまま書くことで対応(プラグイン探すのめんどくさいし)
pipeline { agent any triggers { cron('H/15 * * * *') } options { buildDiscarder(logRotator(numToKeepStr: '10')) } parameters { string(name: 'ID', defaultValue: 'id', description: ID') password(name: 'PASS', defaultValue: 'pass', description: 'PASS') } stages { stage('build') { steps { sh 'echo "build step"' } } stage('test') { steps { script { try { sh 'echo "test step"' } catch(e) { retry(2) { sh "retry step" } } } } } stage('user input test') { steps { script { try { input message: 'このまま処理を進めますか?', ok: 'OK' } catch(e) { echo "中断しました。" return } } } } } post { failure { sh 'echo "failed"' } cleanup { sh 'always success or failed' } } }