aws-vpccreate push したった

gem push するにはアカウント必要らしい。rubygems.org にアカウント作成して push しました。とりあえずもう少し面倒見る必要があるみたいなんだけどどうしたものか。
つうか README.md な Usage に TODO が残ってるのを発見。とほほ。

控え

とりあえず諸々について、ということにて。
gem 作る云々については以下を参考にしました。

bundle gem で雛形を作成した後で以下を参考にさせて頂きつつ rspec なソレをでっちあげました。

あとは Rakefile を以下にして

require "bundler/gem_tasks"

root = File.dirname(__FILE__)
tasks_dir = File.join(root, "tasks")
$:.unshift(tasks_dir)
$:.unshift(File.join(root, "lib"))

Dir[File.join(tasks_dir, "**", "*.rake")].each do |task_file|
  load task_file
end

task :default => :spec

tasks ディレクトリに以下を投入してます (名前は rspec.rake)。

# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

desc 'Run RSpec code examples'
task :spec do
  opts = ['rspec', '-c']
  if ENV['DEBUG']
    $DEBUG = true
    opts += ['-d']
  end
  opts += FileList["spec/**/*_spec.rb"].sort
  cmd = opts.join(' ')
  puts cmd if Rake.application.options.trace
  system(cmd)
  raise "Command failed with status (#{$?.to_i}): #{cmd}" if $?.to_i != 0
end

あとは aws-sdk な試験を参考にしつつ wrapper の試験と実装を書いた次第です。

新環境にて

bundle install 時に nokogiri 導入において libxml2-dev、libxslt-dev が、と叱られました。なかなか色々大変そう。あと、rails なソレも云々しとかにゃ。
とりあえず RubyonRailsTutorial3 なナニを clone して bundle install したりなど。

stub

rspec には method stub (?) な機能があって、aws-sdk もそれをフルに使って ut が記述されておりました。今回作ったソレは基本的に aws-sdk に用意されてるメソドの wrapper でしかないので、動作確認のための試験を作るのに aws-sdk な試験をがっつりパクらせて頂いています。
とは言え、この stub という機能が非常に良いですね。例えば aws-sdk では vpc を作る場合、AWS::EC2::VPCCollection というクラスの create というメソドを使うんですが、基本的には ec2 なオブジェクトを認証情報な辞書を使って取得しておいて以下のように呼び出します。

  vpc = ec2.vpcs.create('10.0.0.0/16')

呼び出される AWS::EC2::VPCCollection#create の定義は以下になってて

      def create cidr_block, options = {}
        
        tenancy = options.key?(:instance_tenancy) ?
          options[:instance_tenancy].to_s : 'default'

        client_opts = {}
        client_opts[:cidr_block] = cidr_block
        client_opts[:instance_tenancy] = tenancy

        resp = client.create_vpc(client_opts)

        VPC.new_from(:create_vpc, resp.vpc, resp.vpc.vpc_id, :config => config)

      end

client.create_vpc の中で aws との間の API なやりとりが行なわれているものと思われます。ここを method stub を使って誤魔化す訳です。
まず stub が戻すソレを設定しておいて

          let(:response) { client.stub_for(:create_vpc) }

あるいは辞書も用意しておいて (戻ってくるデータとしての)

          let(:vpc_details) {{
            :vpc_id => 'vpc-12345',
            :state => 'pending',
            :cidr_block => '192.0.0.0/16',
            :dhcp_options_id => 'dopt-12345',
            :instance_tenancy => 'default',
          }}

before なブロックでこのデータを response に設定しつつ、stub してよね、という命令を記述しておきます。

          before(:each) do
            response.data[:vpc] = vpc_details
            client.stub(:create_vpc).and_return(response)
          end

あとは、stub 呼び出し時の引数の確認とか戻りの確認 (これはそう設定しているのでそれが戻って当然なんですが) をすれば良い訳です。

          it 'calls #create_vpc on the client' do

            client.should_receive(:create_vpc).
              with(:cidr_block => '10.0.0.0/16', :instance_tenancy => 'default').
              and_return(response)

            vpcs.create('10.0.0.0/16')

          end

あるいは以下のように stub な戻りがオブジェクトに設定されているような確認もできる訳でこれは非常に便利。

          it 'returns a VPC object' do
            vpc = vpcs.create('192.0.0.0/16')
            vpc.should be_a(VPC)
            vpc.vpc_id.should == 'vpc-12345'
            vpc.cidr_block.should == '192.0.0.0/16'
            vpc.dhcp_options_id.should == 'dopt-12345'
            vpc.instance_tenancy.should == :default
          end

こんなことが手軽に行なえると試験もとても書き易いですね。すばらです。

ログ的な情報を辞書に残して参照できるようにしてますが、確保したオブジェクトの instance id 的な情報も確保しておいた方が良いな、と思っています。余裕があれば修正の方向ってことで。