Furyu
[フリュー公式]

Tech Blog

フリュー株式会社の技術ブログです

2018年12月14日

araki

Google Apps Scriptで勤怠管理用のSlack Botを作りました

この記事は フリューAdvent Calendar 2018 の12/14分です。

こんにちは。ピクトリンク事業部開発部の荒木です。普段はピクトリンクというアプリのAndroid版を開発しています。最近発売されたスマブラSPが気になっていますが、時間が溶けるのが怖いので買うかどうか悩んでいます。

今回の記事では、Google Apps Scriptを使って勤怠管理用のSlack Botを作った話をしたいと思います。

作ったもの

Slackの勤怠管理チャンネルに、今日誰が休むのかを投稿してくれるBotを作りました。これまで、今日誰が休むのかはSlackチャンネルを遡らないと分かりませんでしたが、このBotによってその問題が解決されました。

以下のように、勤怠の情報を勤怠管理チャンネルに投稿しておくと

スクリーンショット 2018-12-12 10.46.37

毎日、始業前に今日の勤怠情報を投稿してくれます。

スクリーンショット 2018-12-12 10.40.44

※ FTはフレックスタイムのことです。

使っているもの

勤怠管理Botで使っているものは、以下の2つです。

Slack Outgoing Webhooks

Slack Outgoing Webhooksは、Slack上の特定の文字列をトリガーとして指定したURLにPOSTリクエストを投げられる機能です。POSTリクエストには、投稿者や投稿した本文といった情報が含まれています。

Google Apps Script (GAS)

Google Apps Script(以下ではGASと呼びます)は、Javascript互換のスクリプト言語です。特徴は、Google Apps(Googleドキュメントやスプレッドシートなど)を操作するためのAPIが用意されていることです。また、GASはGoogleドライブ上で保管され、時間やHTTPリクエストをトリガーにして動作させることが可能です。

システム構成

勤怠管理Botのシステム構成は以下のようになっています。動作は、勤怠記録と勤怠集計に分かれます。

KintaiBotシステム構成

勤怠記録

スクリーンショット 2018-12-12 10.46.37

上記のような勤怠に関する投稿をスプレッドシートに記録します。

Slack Outgoing Webhooksによって、GASの勤怠記録コードにこの投稿の情報が含まれたPOSTリクエストが投げられます。
勤怠記録コードは、

  • 勤怠対象日:上記の投稿では 12/11
  • 勤怠種別:FT
  • ユーザー名:araki
  • 本文:【FT申請】2018/12/11(火) 10:30 私用のため
  • SlackのユーザーID:POSTリクエストに含まれているSlackのユーザーID

を記録します。勤怠対象日と勤怠種別については、投稿の本文から正規表現で抽出します。

実際に勤怠情報をスプレッドシートに記録する部分は以下のようになっています。最後の行で、GASのAPIを呼び出しています。

※ GASではなくTypeScriptで書かれています。claspというツールで、GASに変換して使っています。

勤怠集計

スクリーンショット 2018-12-12 10.40.44

「Reminder: 今日の勤怠は?」という文字列をトリガーにして、Slack Outgoing WebhooksでGASの勤怠集計コードにPOSTリクエストを投げています。

今日の勤怠情報のみを集計する部分は以下のようになっています。

※ このコードもGASではなくTypeScriptで書かれています。

作ってからのこと

自分や一緒に働くメンバーからどんどん要望が出てきたので、少しずつ叶えていきました。

  • 勤怠種別ごとに出力してほしい
  • 出力のインデントを整えたい
  • 登録できたことを通知して欲しい
  • 現在登録している勤怠情報を出せるようにしたい

まだ叶えていない要望もあります。

  • 間違えて登録した勤怠情報を削除したい
  • 曜日も出して欲しい

これだけ要望が出てくるということは、みんなにあるのが当たり前と思ってもらえるようになったのかなと思います。

さいごに

今回、勤怠管理Botを作ってみて、GASで気軽にいろんなことができるということがわかりました。何より、自分が作ったものが一緒に働いているみんなに使ってもらえて、直接フィードバックがもらえるというのがとても嬉しい体験でした。

みなさんも、Google Apps Scriptで何かを作ってみてはいかがでしょうか?


2018年12月13日

Gradle Kotlin DSLやってみた

こんばんはこんにちは、フリューのジョンです。
この記事はフリューAdvent Calendar 2018の12/13分となります。

2018/12/15 JJUG CCC 2018 Fall にて 既存アプリケーションでKotlinを導入してみた というタイトルで登壇します。
そのKotlinつながりでGradle Kotlin DSLについて書こうと思います。

Kotlin DSLとは

さてさてGradleのところを調べていると最近Kotlinという単語を見るようになりました。
どうやら Groovyではなく KotlinのDSLで書こうということらしいです。
個人的に触って感じているメリットとしては、「アプリケーションがKotlinならそのままKotlinでタスクなどを記述できる」という点でしょうか。
既存の書き方より優れている点は今のところは思い当たらないです。

Gradleプロジェクトを作成しよう

Gradle Initializrを使ってみましょう。 せっかくだからKotlinプロジェクトを選択します。

スクリーンショット 2018-12-12 11.40.30

downloadできたzipファイルを解凍して、IntelliJで開いてApp.ktにあるmain関数を実行してみましょう。

スクリーンショット 2018-12-12 13.42.30

Hello Worldとコンソールにでましたね。とりあえず、Gradleプロジェクトとしてアプリケーションが作成できていそうです。

Gradleタスクを書いてみよう

以下のようにbuild.gradle.ktsにタスクを追加してみましょう

// build.gradle.kts
tasks {
task("helloWorld") {
doLast { println("hello kotlin dsl world") }
}
}

動かしてみましょう。

$ ./gradlew helloWorld

以上です。hello kotlin dsl worldと表示されましたか?

まとめ

1.0になって間もなく、IntelliJで開いてもエラーと表示されているなど、使っていると壁にぶつかるところは多いと思います。
なので、本当に頑張る場合は、公式のサンプルを見比べながらタスクを作成してみてください。

Kotlin DSLガイド
Kotlin DSLサンプル


2018年12月12日

Hashimoto Naoto

ESXiサーバ上で動作しているゲストサーバの詳細情報一覧を取得したい

ピクトリンク事業部開発部インフラ課の「メガネとマスクを同時着用すると耳が痛くなる系エンジニア」の橋本です。この上さらにヘッドホンとか装備しようものなら、耳が爆発します。

 

本記事は フリューAdvent Calendar 2018 の12/12分です。

 

前回の記事で、ESXiサーバにパスワードなしで簡単にSSH接続できる環境を整えました。

今回はそれを活かしつつ、ESXi仮想環境をより便利にしていきます。

やりかた

  1. いい感じに必要情報を取得するスクリプトを作成する
  2. SSH越しにスクリプトを実行する

いい感じに必要情報を取得するスクリプトを作成する

ESXiホストサーバでは、「そのホスト上で動作しているゲストサーバの概要を取得するコマンド」が用意されています。

しかし、これで取得できる情報は、登録されているゲストサーバ名とvmイメージのpath, イメージのバージョン情報くらいのもの。かなり限定的です。

 

個人的見解ですが、少なくともホストサーバの稼働状態(起動中・サスペンド中・停止中)は知りたい。
できれば、いつから稼働しているかとかの情報もわかると嬉しい。

 

そういう詳細情報まで取得したい場合、ESXiに用意されているget.summaryコマンドを使います。

これを叩くと、ずらずらっとjsonモドキの形式で情報が取れます。

出力結果は長いので省略しますが、割り当ててあるCPUのコア数であるとか、いろいろな情報が出ます。

 

ですが、ここで問題となるのが「対象となるVMのID」を指定しなければならない、というところ。

 

ホストの情報は1ホスト分ずつしか取得できず、しかもそのためにはVMのIDが必要なのです。(VMID自体は上記のgetallvmsで取得できる情報です)

 

なので、これらをいい感じに組み合わせるスクリプトを用意しました。

シェバンが #! /bin/sh となっていますが、ESXiサーバで使えるのは /bin/bash ではなく/bin/sh です。
bashとは一部記法が違ったり、たとえば配列みたいな構造体が使えなかったりします。

実行権限付与をお忘れなきよう。

 

実行してみると、こんな感じの結果が帰ってきます。

スクリプト21行目のgrep以降、

この部分で取得する情報を絞っているので、たとえば「IPアドレス情報も取得したい!」という場合には

といった具合に、取得したい項目を追加してやれば良い感じになります。

SSH越しにスクリプトを実行する

esx構成

こんな感じに複数のESXiサーバから単一のストレージサーバ(仮にhoge_fuga_maxheartとします)をマウントし、そこにスクリプトを置いてやれば、どのサーバからも先ほどのスクリプトが叩けるようになります。

ssh越しに複数サーバのスクリプトを叩くには、接続用の鍵ファイルを置いてある環境で下記のようにします。

前回の記事でパスワードなしにSSH接続する環境が整っていれば、一発で全てのホストサーバの状態を取得できます。情報を取ってくるだけなら、このコマンドを都度叩くだけで解決です。

あとはイイカンジのGUIのガワを作って、URLにアクセスがあるたびに情報を取ってきてやれば、見た目にも優しい状態確認画面の完成です。

esx_kanseizu


2018年12月11日

furusin

指定したURLへのアクセスをcronのように定期実行する

こんにちは。ピクトリンク事業部の古川です。

この記事はフリューAdvent Calendar 2018の12/11分となります。

今回は、URLへのアクセスを定期的に実行してくれるWebサービス「cron-job.org」についてです。

はじめに

自分でWeb APIを立てて、GETやPOSTを定期的に実行したい時はないでしょうか。

私の場合、個人的にFirebase Cloud FunctionsにRest APIを作ったものの、定期的に実行する方法が無かったので色々な方法を探していました。

Firebase Cloud FunctionsのAPIを叩くためだけに別のサーバを建てるのは…うーん…

と考えていた時に出会ったのが、このcron-job.orgでした。

ちなみに日本語版はありません。英語とドイツ語のみです。

ですが非常に簡単なので、下記に説明しますのでご安心ください。

あ、あとオープンソースなのでコントリビュートも可能なようです。

実際に使ってみる

cron-job.org にアクセスしましょう。英語ですが大丈夫です。

スクリーンショット 2018-12-04 15.19.49

ユーザー登録する

登録は簡単ですので、画面右上の「Signup」から必要事項を入力して「create free account」をクリックしましょう!

スクリーンショット 2018-12-04 15.27.58

実際にジョブを作成する

画面右上の「Members」から「Cronjobs」を選択し、「Create cronjob」を押下します。

スクリーンショット 2018-12-04 15.30.27

cronを実際に作成する画面は以下のようになっています。

設定できる項目

  • HTTPの認証
  • 定期実行の時間的条件
    • ◯分ごとに実効する
    • 毎日◯時◯分に実行する
    • 毎月◯日の◯時◯分に実行する
    • 自分で決める(複数選択可)

私がやりたかったのは「5分毎にFirebase FireStoreの情報を更新する」ことだったので、

「Every 5 minutes」として設定して実行しました。

時間の色々な選択肢があるのはステキです。

スクリーンショット 2018-12-04 15.38.31

 

リクエストに失敗し続けたらどうなるの?

たとえばRest APIサーバが死んでいて、リクエストが失敗し続けたとしましょう。

その場合、以下のような内容でメールが来て「めっちゃ失敗してるからCron-Job止めたやで!」と知らせてくれます。

まとめ

いかがでしたか?

cron実行だけのためのサーバを建てずとも、簡単にHTTPリクエストを送り続ける設定を作ることができました。

失敗したときもメールで知らせてくれますし、個人で使うには便利なツールかと思います。

ちなみに、つい先日Google Cloud Platformに「Google Cloud Scheduler」が登場したようです。

cron-jobsと似たような動きをしてくれるもののようですので、そちらも試してみてもよいかもしれません!


2018年12月10日

awata

社内のproxyサーバと折り合いを付けたやりかたの紹介

こんにちは。
ピクトリンク事業部開発部インフラ課の粟田です。

フリュー Advent Calendar 2018の12/10分の記事になります。

今回はみんなが大嫌いな(はずの)proxyについて書きます。

問題

弊社のproxyは管理部署が違うため、設定変更できないです(前提)。
なので、proxyの設定変更をすれば良いという意見は聞きません!

  • 社内のproxyがDIRECT接続を設定していない。
    • proxyを設定したままだと社内のサーバに繋がらない。
    • 設定を消すとgithubなど外部のサービスに繋がらない。
  • ブラウザ設定(Windowsの場合はIEから設定するシステム用)のproxy設定にproxy.pacを設定している。
    • Linux上のコンソールで作業する時、http_proxy環境変数などにproxy.pacを設定できない(しても効かない)。
    • 最近はactive directoryで自動配信(IE上などで「自動的に設定する」となってる)になったので、proxy.pacの在処がわからない。

といった事が発生しますよね。

特にDIRECT接続が設定されていないのは問題があります。
たとえば、プログラムのコンパイル時など、社内/社外両方のリポジトリからライブラリを引っ張ってくる時とかに非常に困るんです。

暫定対策

自分一人だけが、手っ取り早くなんとかするというのなら、proxy用の環境変数の設定が早くできれば良いので、以下を実施していました。

  1. 社内のproxyサーバの情報を取得する
    proxy.pacをダウンロードするなり、人に聞くなりの手段にて。
    以降の説明では社内proxyを“192.168.100.10:3128”とします。
  2. proxy設定用のスクリプトを作成する
    proxy.shみたいなファイルを~/binとかに配置
  3. ~/.bashrcとか~/.zshrcとかにaliasを設定

    ’.’ を指定してあるので、sourceを指定しているのと同じ意味合いになります。
    なので、呼び出したshellに環境変数が設定された状態を作ることができるようになる訳です。
  4. proxyの要否をコマンド実行時に切り替え

    とか

    してからネットワークを使うコマンド実行

ビルドプロセス中とかでない場合、またはビルドプロセスでも外部のリポジトリに依存している物をローカルに先にキャッシュしておく、などで同時接続を防ぐ事ができるなら、まぁこれで許容できるかな、という感じですね。
これで一旦は切り替えが楽になったけれども、やっぱり一々切り変えるの面倒じゃないですか?

今実施している別の対策

多段proxyを自分のローカルPC上に建てました。
普段の作業をLinuxのコンソールで実施しているので、パッケージでsquidインストールして常に環境変数設定しとけば良いやん、と。

って、.bashrcか.zshrcに書いときゃえーやん、と。

なので、ローカルPCにsquidをインストールして、設定を記述。
ローカルなネットワークドメイン名とかは当然知っているものとして、squid.confのコメントを便りに設定しました。

以降では社内ドメインとして以下の2つを使用します。

  • example1.com
  • example2.com

また、社内LANのIPレンジとして以下の2つを使用しているとします。

  • 192.168.20.0/24
  • 192.168.100.0/24

2つづつ定義してあると、自分の環境に併せて編集する際に書き方わかるので良いかな、と……

proxy設定はiptablesなどの設定とかでもある様に定義する順番が重要だったりします。
ちゃんとサンプルファイルやコメントを見ながら自分の環境に併せるの重要ですよ!
以下、軽く解説

  • 1〜12行目は、ポート設定ですね。パッケージデフォルトの設定にも入っているかと。
  • 13〜15行目でローカルのネットワーク情報を設定してあります。
  • 16〜25行目で許可設定ですね。順番大事(許可してから全部塞ぐ)です!
    特に重要なのは23行目で、ローカルのセグメントには必ずDIRECTアクセスさせる所ですかね。
  • 26行目で新しく建てるproxyのポートを設定(デフォルト!)
  • 27〜28行目で社内プロキシ(転送先)を指定します。
  • 29〜35行目は無視するとして(よくわかってない)
  • 36行目でPCのホスト名をちゃんと設定しましょう。
    squidが返すエラーページにこのホスト名が載ってきます。localhostは適当過ぎる!
  • 37行目は無視するとして(よくわかってない再び)
  • 38行目でローカルのセグメントではない物のDIRECTアクセスを拒否してます。
  • 39行目はいらないかもしれないけれども、過去に上手く動かないものがあったので、サーバ名(ドメイン名指定なし)でブラウザアクセスした場合などに、サーバ名(ドメイン名指定あり)に変換する際のドメイン名になります。
    ※ 逆に邪魔になる時もあるので注意する。不要なら消しても影響ないはず。
  • 40行目は記載の意味が良くわからないですが、キャッシュしない(キャッシュプロキシとして動作しない)為の設定だそうです。
    (「キャッシュしない」のを「全て」で「拒否」する、と読んだら全部キャッシュしそうな気がしません?)

あとがき

長年戦ってきた社内proxyと折り合いを付ける為だけに頑張ってみた結果こうなりました…

本当はもう1つ問題があるけれども、完全に弊社の問題なので割愛。