Azureの小ネタ (改)

~Azureネタを中心に、色々とその他の技術的なことなどを~

AutoRest フレームワークを使って Azure SDK for Javaを生成してみる

何度かBLOGってますが、Azure SDKはSwagger API (JSON) から 自動でSDKを生成しています。SDKに依存しないピュアなコードも生成できるみたいなのですが、そこは割愛してAzure SDK for Java を生成してみます。

github.com

ビルド

上記、GitHubからリポジトリをクローンします。Java向けは「javavnext」ブランチなので、切り替えてます。ビルドは以下で説明されています。

autorest/building-code.md at master · Azure/autorest · GitHub

かいつまんで説明しますと

  • VS 2015 Update2 と、 CoreCLR RC2 が必要
  • Java 1.8 が必要、JAVA_HOMEの設定をお忘れ無く
  • gradle が必要、2.6 と書かれてますが、最新で問題ないかと思います Download Gradle l Open Source Enterprise Build Automation からインスコしてPathに通しておきます
  • 普通のJava向けだけ欲しいのですが、Androidも一緒にJavaでひとくくりみたいなので、23.0.1 以上のAndroid SDKが必要です。必要に応じてANDROID_HOME の設定します
.\gradlew.bat build

順調にいくと、.\binaries\net45 配下に DLLとかEXEができあがります。 .\binaries\net45\autorest.exe を叩くと

f:id:StateMachine:20160621105409p:plain

こんな感じでヘルプが表示されます。コード生成オプションが見えますが、Azure.Java と Javaでちょっと違う仕様みたいですね。Fluent APIも生成できるような感じです。

コード生成

Azure SDKのSwagger APIの定義は、以下で公開されています。

GitHub - Azure/azure-rest-api-specs: The source for REST API specifications for Microsoft Azure.

とりあえず、以下を実行してみますと、

.\binaries\net45\AutoRest.exe  -input https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/2016-03-30/swagger/compute.json

GeneratedフォルダにC#のソースが出まが、Java向けは以下のようにオプションを指定する必要がありあmす。

.\binaries\net45\AutoRest.exe  -input https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/2016-03-30/swagger/compute.json -CodeGenerator Azure.Java -Namespace hoge

Generatedフォルダの様子。

f:id:StateMachine:20160621110620p:plain

Fluentはまだ生成できませんでした、残念。

Azure REST API Specifications をパースしてモデル情報を見てみる その2

前回は、Swagger APIのパース部分でつまづいて終わったのですが、続きをやってみました

statemachine.hatenablog.com

Parser

前回記事通り、現状のSwagger製のJava Parserだと、Azure の REST API SPECが正しくパースされないので、結局Java Parserをアドホックに修正して自分の希望通りにパースできるようにしてみました。あまり厳密な解釈にこだわる必要もないので。

Diagram

詳細は後述しますが、ComputeのAPIをモデル化した情報をDiagramエディタにD&Dして、手動レイアウトしたものが以下です。

f:id:StateMachine:20160519131716p:plain

VirtualMachineから関連するオブジェクトが手に取るように分かります。これで内部構造の理解も捗るんじゃないかと思います。

仕組み

前回も少し書きましたが必要な環境は以下です。

  • Eclipse 4.6 Modeling edition
  • Eclipse Modeling Framework(EMF)
  • Swagger Parser
  • API の スキーマ

EclipseにはJava IDEとかとは別に、Modeling Editionがありますので、これを使います。EMFやDiagram Editorなどのプラグインが予め組み込まれています。

やっていることは簡単で、APIをパースするとSwaggerのAPIモデルが作られます。クラスやプロパティ、関連などが機械可読可能な状態になりますので、それをEMFのEcoreモデルでモデリングするだけです。EMFのEcoreモデルはメタモデル(MOF)の実装です。簡単にいってしまえば、Swagger API JSON -> Ecoreモデル(*.ecoreファイル)の変換をしているに過ぎません。

ecoreモデルが出来た後は、Diagram Editorを開いてD&Dしつつ、見える形に整えるだけです。

というわけで、当初も目論見が達成できたので満足です。

Azure REST API Specifications をパースしてモデル情報を見てみる

以前、手書き(UMLツール)で以下を作図したんですが、手書きで書き起こすのはちょっとシンドイです。

statemachine.hatenablog.com

この手の物には、機械可読可能なメタモデル的な定義があるわけでして、それが何かというと以下だったりします。

GitHub - Azure/azure-rest-api-specs: The source for REST API specifications for Microsoft Azure.

これはSwagger のJSONスキーマで定義されているので、パースすれば何らかのモデル情報を読み出せると思ったので試してみました。

当初の目論見では、

  1. JSONをパース
  2. パースした内容をEMF(Eclipseメタモデルフレームワーク)でモデリングするPGを書く。EcoreでもUMLモデルでもどちらでも。
  3. 生成したモデルをGUIエディタにD&DするとDiagramができあがり。

なんてことを夢想しましたが、まだ出来ていません。

パース

Swaggerのツールセットは以下にあります。Swagger謹製のフレームワークもいくつかあります。

Open Source Integrations – Swagger

とりあえず、JavaのSwagger Parserを使ってみます。

github.com

ちなみにAzure ARM APIで使っているAutoRestも列挙されています。

パースはとても簡単で、以下を実行するだけです。リンクを直接読んでくれます。リンク先は、Azure ARM API Computeのスキーマです。

String url = "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/2015-06-15/swagger/compute.json";

SwaggerParser parser = new SwaggerParser();
Swagger swagger = parser.read(url);

swagger.getDefinitions() から定義されたモデル情報が取得できますので、適当にたどって表示させてみましょう。 例えば、VirtualMachinePropertiesというモデルのプロパティを表示させると、以下のようなプロパティ群を持つことが分かります。

** VirtualMachineProperties **
desc  : Describes the properties of a Virtual Machine.
  hardwareProfile      : ref -> #/definitions/HardwareProfile
  storageProfile       : ref -> #/definitions/StorageProfile
  osProfile            : ref -> #/definitions/OSProfile
  networkProfile       : ref -> #/definitions/NetworkProfile
  diagnosticsProfile   : ref -> #/definitions/DiagnosticsProfile
  availabilitySet      : ref -> #/definitions/SubResource
  provisioningState    : string              
  instanceView         : ref -> #/definitions/VirtualMachineInstanceView
  licenseType          : string        

なんか良い感じです。タブン、頂点のVirtualMachineモデルからたどって行けばなんとか行けそうです。

allOf

で、VirtualMachineモデルのパースがうまくいきません。スキーマとして allOfを持っているとこちらが望んだ形でパースされないことがわかりました。スキーマの該当部分は以下です。properitesをパースしてくれない感じでした。

    "VirtualMachine": {
      "properties": {
        "plan": {
          "$ref": "#/definitions/Plan",
          "description": "Gets or sets the purchase plan when deploying virtual machine from VM Marketplace images."
        },
        "properties": {
          "x-ms-client-flatten": true,
          "$ref": "#/definitions/VirtualMachineProperties"
        },
        "resources": {
          "readOnly": true,
          "type": "array",
          "items": {
            "$ref": "#/definitions/VirtualMachineExtension"
          },
          "description": "Gets the virtual machine child extension resources."
        }
      },
      "allOf": [
        {
          "$ref": "#/definitions/Resource"
        }
      ],
      "description": "Describes a Virtual Machine."
    },

ソースみたり原因さぐっていると、以下のIssueが見つかりました。どうも、そういうスキーマっぽい感じです。

Swagger is not parsing definitions with properties along with allOf · Issue #141 · swagger-api/swagger-parser · GitHub

AutoRestにも言及されていて、AutoRestのほうはヨロシクパースしてくれるんでしょうね、きっと。

というわけで、道半ばではありますが、備忘録変わりにBlogっておきます。Parserに手を入れて続けてみようかと。