読者です 読者をやめる 読者になる 読者になる

ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

OpenStack クライアント開発日記 (2)

重要なお知らせ

プロジェクトの名前が yao になった。

github.com

背景として、OpenStackのPythonのライブラリにすでに Oslo なるものが存在した。

さすがにOpenStackというドメインでかぶってるのはかなり渋いので変更した。(oslo.gemは「oslo gem」とか「oslo ruby」とかで事前検索した結果見つからなかったのでつけてしまった...)

yao というのは Yet Another Openstack libraryの略。工夫がないですね... しかし短いし、何より取れてしまったのでこれで。そこはかとなくアジアンな響き。

sed万歳!

JSONをオブジェクトっぽく扱う実装のメモ

難しいことはしたくなかった。以下の方針でやっていった。

  • イニシャライザに渡すHashを普通に持っておく
  • Resource#[],#[]= をそのHashに移譲する
  • よく使う奴はクラスマクロでまとめてメソッドにする

こういうことやってくれるgem(たとえばhashie)はあるけど、機能が多すぎるし、依存を小さくしたいので自分でひょろっと書く。

OpenStackのJSON、幾つか渋い要素があって、

  • キャメルケースとスネークケースが混ざってる
  • "OS-FLV-DISABLED:disabled" みたいなキーがある

その二点の要件を満たすべくこんな感じで書けるようにした。

module Yao::Resources
  class Flavor < Base
    # そのまんまメソッド名に対応できるキーを列挙
    friendly_attributes :name, :vcpus, :disk, :swap

    # キャメルケースのキー、複雑で渋いキーはエイリアス
    map_attribute_to_attribute "os-flavor-access:is_public" => :public?
    map_attribute_to_attribute "OS-FLV-DISABLED:disabled"   => :disabled?
  end
end

あと、これらのパターンにあてはまらないような属性もあるんで、そういうのはこう、子クラスでメソッドを普通に定義すればいいと思う。普通って素晴らしい。

module Yao::Resources
  class Image < Base
    def size(unit=nil)
      size = self["OS-EXT-IMG-SIZE:size"]
      case unit
      when 'K'
        size / 1024.0
      when 'M'
        size / 1024.0 / 1024.0
      when 'G'
        size / 1024.0 / 1024.0 / 1024.0
      else
        size
      end
    end
  end
end

OpenStack、拡張が幾つかあって環境によって取れる値に微妙に差があるので、全部をメソッド化するのは辛い。その辺は Resource#[] で取ればいいかなと思った。必要ならPRする方向でひとつ。

それからもう一つあって、SecurityGroup関連のリソースが、novaで取得した時とneutronで取得した時とで微妙にフォーマットに差がある...

辛いけど頑張って抽象化した。うまくいってるかは徐々に検証して修正する。ご興味があればこの辺眺めてください。

ここまでで、一応、インスタンスも立てられるぞ!

Yao::Server.create(
  availability_zone: "test",
  imageRef: "b4bd717c-7bf9-4c53-a40b-XXXXXX",
  flavorRef: "123",
  networks: [
    {uuid: "e3783d02-a10e-44d9-8957-XXXXXX"},
    {uuid: "c114be43-5a59-4046-b9c1-XXXXXX"}
  ],
  name: 'udzuradayo.novalocal',
  key_name: 'sample001'
)

そしてそろそろ

自動テストを書かないとね...