Office 365を知る参考書(?)

Office 365とかAzureについていろいろ書きたいと思います。別に参考書ではありません。韻踏んでみたかっただけです。

TeamsでChatOps!? TeamsからAzuru FunctionsとAzure Automationで仮想マシンの管理を行なう

先日タイに出張していたのですが、連日30度を越えていて非常に暑かったです。
帰ってきたら20度以上の温度差で少し風邪をひいてしましました。体調管理には気を付けたいものです。

さて今回は思い付きのアイディアを形にしていく自由研究スタイルでいきたいと思います笑
私は検証用にAzureで仮想マシンを動かしておりますが、やっぱり節約しなきゃ!ということで小まめに停止をしております。
ただ毎回Azureのポータルで操作するのってやっぱり面倒くさいですよね。
ということで、TeamsのBot経由でやってしまおう!というのが今日の内容です。今回は仮想マシンの停止のみですが、スクリプトの書き方によってはもちろん仮想マシンの起動や作成、インスタンス変更なんかもできます。すべてはスクリプトの書き方次第でどうとでもなります。
そんなプチChatOps(そんな大それたものではないけれど)が今回のテーマでございます。
Azureを使うのでサブスクリプションが無い方は試用版を取得しておいてください。

やろうとしていること

今回はシンプルに以下のような流れを想定しています。
Microsoft TeamsでBotユーザーに対して特定の文字列(stop-vm)を打つとAzure FunctionsにHTTPリクエストを投げる
②Azure Functionsが起動し、ユーザーに対してメッセージを返すともにAzure AutomationにHTTPリクエストを投げる
③Azure Automationが仮想マシンの停止スクリプトを実行
仮想マシンのシャットダウンが完了したらIncoming Webhookでユーザーに通知

とっても雑な絵ですが、こんな感じ。
f:id:takeru55555:20171207175039p:plain

直接Azure Automationに投げてもできるかもしれませんが、Azure Functionsを経由した方がインタラクティブに対応できますし、これから開始や仮想マシンごとの停止、インスタンスの変更などを考えたときにFunctionsの方が自由度が効くと思ってこうしております。

これを実現するために、以下の準備を行います。

1.一連の処理が終わったら特定のチャネルにメッセージを送信できるようにIncomingWebhookを用意しておく
2.Azure Automationで仮想マシンの停止のRunbookを用意しておく
3.Azure Functionsで関数を用意しておく
4.Teamsにカスタムボットを登録し、Azure FunctionsにHTTPリクエストを投げれるようにしておく

それではそれぞれ見ていきましょう。

1. Teams側でIncoming Webhookを追加しておく

こちらは以前の記事を参照して用意しておいてください。
f:id:takeru55555:20171215004100p:plain

2. Azure AutomationのRunbookを用意する

以下のページを参考に、仮想マシンを操作するRunbookを作成しました。
Azure Automation で VM を自動停止する – Japan Azure Technical Support Engineers' Blog

今回は「Runbook の編集」章で記載がある、「サブスクリプション内の、すべての VM」を停止するようにします。

なお、仮想マシンが停止後、Incoming Webhook経由でメッセージを投げるために、後半のforeach文を以下のようにしております。

foreach ($VM in $VMs) {
    # VM を停止
    $StopRtn = $VM | Stop-AzureRmVM -Force -ErrorAction SilentlyContinue
    $URI = <1. で作成したIncoming WebhookのURL>

    # 正常に VM が停止したかの確認&ステータスの出力
    if ($StopRtn.Status -ne 'Succeeded') {
        Write-Output ($VM.Name + " failed to stop.")
        Write-Error ($VM.Name + " failed to stop. Error was:") -ErrorAction Continue
        Write-Error (ConvertTo-Json $StopRtn.Error) -ErrorAction Continue
        $body = ConvertTo-JSON @{
            text  = $VM.Name + " failed to stop."
        }
    Invoke-RestMethod -uri $URI -Method Post -body $body -ContentType 'application/json'
    }
    else {
        Write-Output ($VM.Name + " has been stopped.")
        $body = ConvertTo-JSON @{
            text  = $VM.Name + " has been stopped."
        }
    Invoke-RestMethod -uri $URI -Method Post -body $body -ContentType 'application/json'
    }

Runbookを保存したら、Webhookを追加します。
Webhookの追加をクリック。
f:id:takeru55555:20171215004207p:plain

任意の名前など必要な設定値を入力して作成。URLが表示されるので控えておいてください。
f:id:takeru55555:20171215004249p:plain

3. Azure Functionsを用意する

今回は全てPowerShellで書こうと思いますので、「PowerShell」-「HTTP - trigger」を選択します。
f:id:takeru55555:20171215004644p:plain

とても簡単ですが、以下のようなものを準備しておきました。

$requestBody = Get-Content $req -Raw | ConvertFrom-Json
$text = $requestBody.text
Out-File -Encoding Ascii -FilePath $res -inputObject $input

$vms = Get-Content $inputTable | ConvertFrom-Json
if($text -like "*stop-vm*"){
    $hash = @{
        type = "message";
        text = "OK. Wait a moment.";
    }
    $URI = <2で取得したAzure AutomationのWebhookのURL>
    Invoke-RestMethod -uri $URI -Method Post -body $body -ContentType 'application/json'
}
else{
    $hash = @{
        type = "message";
        text = "please use the folowing comend.<br>stop-vm -vm 'VM name'";
    }
}
$input = $hash | ConvertTo-Json
Out-File -Encoding Ascii -FilePath $res -inputObject $input

stop-vmコマンドが来たら2で作成したAzure Automationに投げる、それ以外はヘルプ的なものを出す、といった形にしています。

こちらもWebhookを追加します。
f:id:takeru55555:20171215020616p:plain

4. Teams側でカスタムボットを追加する

 チームの管理から「カスタムボットの作成」をクリック
f:id:takeru55555:20171215005629p:plain

3で発行したURLや名前、説明を入力し、作成
f:id:takeru55555:20171215161409p:plain

これで準備が完了です。

さっそく試してみる

それでは登録したBotユーザーに対してStop-VMと話しかけてみましょう。
f:id:takeru55555:20171215015819p:plain

VMがシャットダウンされましたね。
ちなみにStop-VM以外を打つと以下のようにヘルプ的なものが出るようになってます。
f:id:takeru55555:20171215015738p:plain

Azure Functionsはタイムアウトする場合があるので、その辺の考慮は必要ですが、簡単ですし応用も効きます。
是非お試しあれ。

さて次回も自由研究系で何かを書いていこうと思います。

ではまた次回。