ラベル SORACOM の投稿を表示しています。 すべての投稿を表示
ラベル SORACOM の投稿を表示しています。 すべての投稿を表示

ゆくSORAくるCOM

2015年12月23日水曜日

SIM Earth

「光あれ」
こうして光回線があった。
C89一日目のことである。
しかし極東の島国に天使が舞い降りた日、文明は歩みを止めた。
人々はそれをインガオホーと受け入れた。いや、受け入れることで自らの思考を縛り、困難から目を逸らしたといったほうが正確だろう。
それから数千年、いや悠久とすら呼べるほどの日々が過ぎ去った。人口が激減し、人類はもはやアンデス山脈の中腹に位置するツンドラ地帯のみに細々と逃げ延びる、トリクロデートに覆われた地球。
幼い日々に目を輝かせて百科事典をめくり続けた彼は、いつしか環境復帰プロジェクトの管理者になっていた。
うみが

じょうはつしています。

きおんをさげてください。
システムからのウォーニングメセッジが自棄に心を打つ。
そんなことはわかってる。もう何世紀も前からわかっているんだ。
そんなことを言われてもどうすればいいのか分からない。
生態系が破壊しつくされた
ジェームズ・ラヴロックに心酔した彼が求めた未来のひとつの形ともいえる。
人々は状況打開の鍵を伝説の書に求めている。
『クラウドデザインパターン』
「そう。過去数世紀にわたって観測されていない"雲"を再びデザインし、雨を降らせ、生態系を復活させることが人類復活のための希望(SIM)なんだ。」
21世紀に戻って伝説の書を入手し、それに従って気候改変をおこなう。
そうだ。SIMによって地球がひとつとなる。
ガイアが、そう囁くのだ。
彼は自らの心にそよ風が巻き起こるのを確かに感じていた。あたかも秩序無用のサーキュレータのように。
「おや、21世紀へ旅立つのかい」
「ええ。この機を逃すと次のチャンスは2,000年後になってしまいますから」
「知ってるかい、21世紀にはトウキョウのアカサカに"みんみん"という"ギョーザ"のおいしいお店があったそうだ。チェーンの"珉珉"じゃない。」
「おいしい餃子情報は大歓迎ですが、なんで今それを?」
「ジョークだよ。意味なんてない。」
そろそろエクソダスの時が来たようだ。
僕はこれに乗って過去を変え、そして未来である現在を取り戻すんだ。
あの日をやり直せるならば。このソラを取り戻せるならば。

SORACOM?

そういうわけでSORACOM Advent Calendarの23日目です。
SORACOM自体については、もはや改めて紹介するまでもなく皆さんご存知だと思うので省略します。
今回は、SORACOM関連で私が今年やったことをまとめます。

SORACOM APIのモックを作った

SoraCommonNetSandboxというものを作りました。これは、次に挙げる.NET版非公式SDKの開発途中で各種APIの呼び出しをほどよくテストする仕組みが欲しくなった結果、副産物として生じたものです。
.NET版非公式SDKの実装範囲しかモックも書いていないので、まだまだ機能が不足していますが、徐々に足していきます。少なくとも、SIMをterminateするAPIを安心して叩けるようになったので私の心には平穏が訪れました。
本家にきちんとしたAPI sandboxがあったほうが嬉しいに違いないのでSORACOMサンタにもお願いしました。本家での実装を楽しみに待ちましょう。
他言語用の非公式SDKを作っている方など、必要があれば適当に叩いていただいて構いません(エンドポイントの記載などは: C#でSORACOM APIのモックを作ったよー。ついでにC# 6+ASP.NET 5で楽にRESTfulサービスを書けてオススメという話にあります)。

.NET版非公式SDKを作った

ASP.NET 5のサーバから自分のSIM一覧を管理する仕組みを書きたかったので、.NET版の非公式SDKを作りました(SoraCommonNet)。
自分で使う機能から順次カバーしていっていますが、網羅度はあまり高くありません。まだ足りないところも結構あります。PCLで作っているのでXamarinにも持っていきやすい、というメリットがあったはずなのですが、携帯端末上から他端末のSIMを管理する仕組みの必要性はイマイチ謎でもあります。
もちろんIoT管理インフラとして考えるとそれなりに妥当性があるのですが、どのみち携帯端末側に持つのはUIのみで処理主体はサーバになるのでは、という気がしますね。
このあたりの経緯は以前SORACOM APIをC#から触れるようにしたで書きました。

APIドキュメントの変更を追跡した

SORACOM APIのリファレンスはそこそこの頻度で更新されています。ページ末尾に記載されているAPIバージョンが同じでも、ドキュメントは細かく改訂されていきます。
.NET版SDKやモックを作っていくうえで(そして、きっと他の言語用のバインディングを作っている方々も?)このドキュメントの更新箇所を把握できたほうが良いと感じたので、個人的に定点観測しています。
要はこのページのソースにあたるJSONデータを取得してきてせっせとdiffを取っています。
データ取得部分のコードはSoracomApiCrawlerとして公開してあります。APIの増減は最低限把握したかったので、生のJSONに加えてAPIサマリ(一覧)も別途出力できるようにしています。
とにかくサーバの運用をしたくない昨今、Azure Web ServicesのWebJobsを使いたかったので使ってみました。
開発に際しては、Azureの管理コンソールが旧ポータルから新ポータルへの移行期間にあたってしまい、片方のコンソールにしかない機能を使うために行き来するストレスがあったり、新ポータルが時折落ちていて作業が進まなかったのですが、今では良い思い出です。
ちなみに、まだあまり使ったことのある人が多くなさそうなAzureの新ポータルでのバッチジョブ画面は図1のような感じです。前よりもだいぶすっきりしました。
  図1 Azureのバッチジョブ画面
定期的に取得したデータはAzureのBLOBストレージへと保存しています(図2)。
図2 AzureのBLOBストレージへたまっていくJSON
Azureのバッチで1日3回取得してBLOB保存したJSONデータは、個人作業の合間や仕事の休憩中たまにAzureのポータルへログインして手動で(!)一覧ページを表示し、更新がありそうならファイルをダウンロードしてJSONのdiffを調べています。
この結果をgistへ貼り付け、コメントと共にTwitterへ流しています。
定点観測していると、案外ソラコム内でのドキュメント更新ではまだ時折ケアレスミスがあり、あるタイミングの記述修正がのちの更新でうっかり巻き戻ってその後さらに更新されて正しくなったりしている、という人間くささを感じられてほっこりします。中の人がんばってますね。
さて、前述の通りAPIドキュメントの定点観測においてデータ取得以外の変更検出と差分抽出は完全に手動作業です。これではさすがに手間がかかるので自動化すべく最近コードを書いています。コード本体よりも周辺環境(ASP.NET 5 RC1+EF7 RC1)のファイル構成がイマイチ安定していない*1ところに時間を取られて度々心が折れています。
年明けには多少マシな感じになるでしょう。
[*1] たとえば、パッケージ名が変わっていたり、VSのプロジェクトテンプレートによって生成される設定ファイルの内容に齟齬があったりと、正式リリース前らしさを感じるものがいろいろあります。

来年もSORACOM

主に.NET圏から眺めたり手を出したりしていきます。
SORACOMで覆われる地球、楽しみですね!
SORACOM Advent Calendar 2015も残すところあと2日となりました。
明日の担当はmana_catさんです。

C#でSORACOM APIのモックを作ったよー。ついでにC# 6+ASP.NET 5で楽にRESTfulサービスを書けてオススメという話

2015年10月23日金曜日

APIモックを作る?

SORACOM APIをC#から触れるようにしたのとおり、先日SORACOM APIの非公式な.NET版クライアントライブラリを書きました。
これについてソラコム Developers Conference #0のLTでひたすら「API sandboxがないので管理クライアントや他言語SDKの開発がつらい」という話をしてから1週間ほど経ちます。
「よーし足りないAPIを追加するかー」と思ったものの、やはり最低限はテスト環境が無いとリグレッション検出などで結構困るので、テスト用のモックサービスを作ることにしました(手間がでかすぎてyabaiというほどでもないし)。
試験前に部屋の片付けをするノリで作ったので本当に最低限だけです*1が、完成したので
置いておきます。本家でsandboxがリリースされたらひっそりとクローズすると思います。
ともかく、心置きなくSIM解約のテストができるの素晴らしい!
以下は、作り方が気になる方のための簡単ASP.NET 5ガイドです。
[*1] パスワード指定ポリシーは本家のAPIに準拠したりしていますが。

構成

  • 開発言語: C# (C# 6)
  • フレームワーク: ASP.NET 5(ASP.NET MVC 6 beta5)
  • 開発環境: Visual Studio Community 2015
  • 稼働環境: Microsoft Azure Web Service(Web Apps無料版)

ASP.NET 5(ASP.NET MVC 6)でRESTfulサービスを作る

ASP.NET 5とDNXの1.0.0-beta8がリリースされてたで書いたようにASP.NET 5はfeature complete状態にあります。つまりコードの安定性はさておき、現時点で提供されているAPIセットはよほどのことがない限り製品版まで変更されないはずです。最悪落ちても辛くない系プロダクトを書き始めるのにちょうど良いタイミングということです。
基本的にVisual Studio 2015(以下VS2015)のASP.NET Web Application内にあるWeb APIテンプレートから作成したものを下地としてリファレンス片手にIntelliSense眺めつつ気合で書き換えていきますが、取っ掛かりとしてはBuilding Your First Web API with MVC 6が良いチュートリアルです。

VS2015でのASP.NET 5 Web Application(preview)プロジェクト作成

VS2015に含まれているASP.NET 5のプロジェクトテンプレートは多少古く、beta5用のものです。
じきにVS自体のアップデートで更新されると思いますが、現段階ではひとまずbeta5を使っておきましょう。
project.jsonの中身を直接書き換えて依存関係を更新する策もありますが、これを書いている時点ではMicrosoft.AspNet.Server.IISだけbeta8版が出ていないので、更新待ちです*2
[*2] 軽い気持ちで混ぜたところやっぱりダメだったので混ぜるな危険。どうしても新betaを使いたければIISをやめてKestrelを使うなど、手はあります。それはそれでハマりそうですが。

レスポンスの返し方について少々メモ

プログラムにエラー処理はつきものです。
当然、RESTfulなAPIでもさまざまなエラー処理が必要です。
Visual Studioのテンプレートから生成されるValuesControllerは普通に各APIからの戻り値をstringIEnumerable<string>と宣言します。こうしておくとASP.NET MVCのランタイム側で適当にJSONへ詰め込んで返してくれます。
このフローは型情報をきっちり書く面ではとても良いのですが、不便なところがあります。HTTPのエラー情報を返すうえで厄介なのです。
従来のASP.NET MVCではこの処理に例外を使っていました。
throw new HttpResponseException(HttpStatusCode.NotFound);
という具合です。
しかしASP.NET 5でこのように書いても単純に内部でハンドルされていない例外が発生した扱いとなるだけです。
ではどうするのかというと、レスポンスをラッピングできるIActionResultというインタフェースに従った値を返すようにします。
HTTPのエラーコードはいろいろありますが、要はテンプレコードです。なるべく省力でカバーしたいものです。
たとえば400のbad requestを返したい場合、ASP.NET MVC的にはBadRequestResultBadRequestObjectResultのふたつの選択肢があります。レスポンスのボディがあるか無いかという違いを考えると、このようにわかれているのは仕方ないのですが、呼び分けるのが微妙に面倒です。
ASP.NET MVCのControllerは至れり尽くせりで、HttpBadRequestというstaticメソッドがオブジェクトを引数として渡すか否かで生成オブジェクトを切り替えてくれます。
これを使って次のようにサクサクとエラー処理を書けます。
  [HttpGet]
  public IActionResult Get()
  {
    return HttpBadRequest(new { foo = "shinchoku", errmsg = "damedesu" });
  }
このあたり詳しくはASP.NET MVC自体のコードを読むのが早いです: https://github.com/aspnet/Mvc/blob/f57e1809716/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs#L970-L1009

粛々とAPI仕様に従ってコントローラを書く

書きます。
最初のうちは動作確認をcurlでおこなっていましたが、途中からFiddlerへ変更してサクサク確認していきました。IEからの通信を自動キャプチャとかとても便利でした。

ASP.NET 5(ASP.NET MVC 6)でサクサクとWeb APIを作る

ASP.NET MVC 6ベースのRESTful API構築は割と生産性高くて良いです。面倒なボイラープレート系のコードはほとんどなく、コーディング時間のうちほとんどをAPI定義→C#コードへの翻訳に使えました。
RESTfulなサービスにおいて、HTTPのリクエストではおおまかに
  • URIのパスにfoo/bar/hoge/fuga形式で記述
  • クエリ文字列に?foo=bar&hoge=fuga形式で記述
  • リクエストボディにJSON({"foo":"bar", "hoge":"fuga"})で記述
とあり、それぞれが結構楽に扱えるようになっています。
今回はクエリ文字列解釈を使っていませんが、それ以外のふたつは
  public class SetGroupRequest
  {
    public List<string> configuration { get; set; }
    public long createdTime { get; set; }
    public string groupId { get; set; }
    public long lastModifiedTime { get; set; }
    public string operatorId { get; set; }
    public Dictionary<string, string> tags{ get; set; }
  }
  [HttpPost("{imsi}/set_group")]
  public IActionResult Post(string imsi, [FromBody] SetGroupRequest req)
  {
    ...
  }
(https://github.com/muojp/SoraCommonNet/blob/master/SoraCommonNetSandbox/Controllers/Subscribers.cs#L145-L155からの抜粋)
というようになります。
  • URIパス内の特定部分に名前をつけて受け取る
  • リクエストボディのフォーマットを規定したら[FromBody]属性をくっつけて受け取る
というのをさらっと書けています。
前述のエラー処理に関するポイントと共におさえておくと、楽にサービスを書き始められると感じました。
C# 6のNull conditional operatorもhttps://github.com/muojp/SoraCommonNet/blob/master/SoraCommonNetSandbox/Controllers/Subscribers.cs#L40のような場所で役に立ちますね。

テストのテストをどうするかという話

Ruby版SDKなど、他言語用のバインディングを使ってテストする策がありますが、今のところこれ自体のテストは書いていません。

適当にデプロイして様子を見る

どうせ誰も使わないので適当に公開しておきます。
Azure Web Serviceの無料版はSSL非対応なのでhttpのみです。またこれは所詮モックで、SoraCommonNet側のコミットフックなどでのテスト実行時のみに利用するものなのでquota的な問題はないでしょう*3
ちなみにこれは無料プランゆえのtipsですが、自動テストから叩く際にはSetUp的なメソッド内で適当なAPIを叩いてスピンアップさせるのが無難です。さもないと序盤のテストケースで10秒程度固まり、標準の2秒タイムアウトだと何かと面倒な感じになるでしょう。
[*3] 無駄に検索エンジンから拾われるのもアレなのでrobots.txtぐらいは置いておいたほうが良いのかもしれません。