2017年10月16日月曜日

Flow のサービス情報を Azure Table Storage に格納し新規サービスを検知する

かねてから LogicApps の新規コネクタについては、毎日検索するようにしていたのですが、今回 Flow についても同様に実施してみました。LogicApps の場合とはちょっと異なる方法でなくてはならないので少しばかりコードを書くことに・・・。

全体的なフローはこのようなものになります。基本的な流れは、LogicApps の時とほとんど同じです。

image

LogicApps と異なり、Flow は Azure LogicApps 基盤で動作しているとはいえ、そのテナントに対して権限を持つアプリケーションを登録することができません。そのため、コネクタ一覧の HTTP サイトの情報をもとに判定を行うようにしています。

image

こちらのサイトのソースを見ると、コネクタについては p タグで特定のクラス名を設定さrているのがわかります。

image

それを踏まえて、サイト情報より api-name というクラス名が設定されている p タグの情報を抽出し、ここからコネクタ情報として判定を行います。

ところが、現在 LogicFlow 上ではこのあたりをうまくやる手段がありません。通常であれば、正規表現を利用して抽出を行ったり、XML 変換して XPath で抽出など行うことが考えられるのですが、正規表現は LogicFlow の関数には存在せず、XML 変換は HTML 側で意識されていないと簡単には変換を行えません。

using System.Net;
using System.Text;
using System.Text.RegularExpressions;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// 渡された値(BASE64エンコード済み)を復号する
string inputBody = await req.Content.ReadAsStringAsync();
Encoding enc = Encoding.GetEncoding("UTF-8");
string input = enc.GetString(Convert.FromBase64String(inputBody));
//正規表現を使って api-name とクラス設定されている箇所を抽出
string pat = @"<p class=\""api-name\"">(?<servicename>.*?)<\/p>";
Regex r = new Regex(pat);
MatchCollection mc = r.Matches(input);
//結果の生成
StringBuilder res = new StringBuilder();
foreach (Match m in mc)
{
res.Append(m.Groups["servicename"].Value + "_");
}
if (res.Length > 0) res.Remove(res.Length -1, 1);
return res.Length <= 0
? req.CreateResponse(HttpStatusCode.BadRequest, "抽出対象の文字列が空です。")
: req.CreateResponse(HttpStatusCode.OK, res.ToString());
}

そのためこのような関数を Azure Function App に作成します。関数に取得したコネクタ一覧の HTML 情報わたし、正規表現にて抽出を行った結果を返却させるというものです。こういった純粋に関数なものは、Function App を利用するのが非常に適しています。

image

Function App から配列で戻してもよかった気がしますが、昔気質な方法で一つの文字列でもどしていますので、Function App の結果を split 関数で配列に変換しています。なお、最初は ,(カンマ)で区切って戻していたのですが、コネクタの中にカンマを名称に含んでいたのがあったので、_(アンダースコア)を利用しています。

image

変換した配列の要素数が、Flow で提供されているサービス数となりますので、それを用いてツイートしています。

image

そして後は、新規に追加された場合の対応ですが、前回は律儀に「Table Storage にデータが存在しているかどうか」で処理を切り分けていましたが、今回はシンプルです。

image

Table Storage よりデータを取得するのですが、この時にキーとなる情報を明示的に指定しています。新規サービスであった場合、このデータ取得アクションが「失敗」しますので、後続のツイートアクションの実行条件を、「データ取得が失敗した場合」と設定します。このように設定すると、デザイナー上で矢印が赤い点線に切り替わります。

こうすることで、取得できたかどうかを判断することなく、新規コネクタかどうかを判定できるようになります。1 アクションといえばそれまでですが、ForEach の中にあるのでサービス数分繰り返されると思うと、こういった方法はコスト削減に直結するので有用です。

このような感じで、Microsoft Flow の新規コネクタ情報も検知するようにしてみました。

0 件のコメント:

コメントを投稿