LoginSignup
8
8

More than 5 years have passed since last update.

ChefのProvidersを活用してServerSpecめいたものを作る、とりあえず一歩目

Last updated at Posted at 2013-05-27

この記事は最終更新から1年以上経過しています。 気をつけてね。

タイムラインにServerSpecの話題がそこそこ見えたので、サーバの受け入れテストに使えるかなと触ってみました。

考え方などとても良いと思いましたが、この先色々なプラットフォームへの対応を書いていくのはいささか大変に感じます。
なのでどうせRSpecを入れるなら、Chefの資産を活用する方向で似たようなものが作れないかと試して見ることにしました。

追記
ServerSpecはサーバ側にRSpec入れるわけじゃないのね。
https://github.com/mizzy/rspec-lxc-test-box/blob/master/spec/support/matchers/be_enabled.rb

概要

  • Ohaiでプラットフォームを判別する
  • プラットフォームからプロバイダを選択する
  • テストのためにCurrentResourceをゲットする

Ohaiでplatformを取得する

これはまあ、以前やった Chefの心臓、Ohaiのアトリビュートを他のプログラムからも拝借したい ですよね。

os, platformプラグインの力を拝借しましょう。

Irb-Out
> require 'chef'
=> true

> ohai = Ohai::System.new
=> #<Ohai::System:0x00000001c73318
 @data={},
 @hints={},
 @plugin_path="",
 @providers={},
 @seen_plugins={}>

> ohai._require_plugin('os')
=> true

> ohai._require_plugin('platform')
=> true

> ohai.data
=> {"languages"=>
  {"ruby"=>
    {"platform"=>"x86_64-solaris2.11",
     "version"=>"1.9.3",
     "release_date"=>"2013-02-22",
     "target"=>"x86_64-sun-solaris2.11",
     "target_cpu"=>"x86_64",
     "target_vendor"=>"sun",
     "target_os"=>"solaris2.11",
     "host"=>"x86_64-sun-solaris2.11",
     "host_cpu"=>"x86_64",
     "host_os"=>"solaris2.11",
     "host_vendor"=>"sun",
     "bin_dir"=>"/opt/local/bin",
     "ruby_bin"=>"/opt/local/bin/ruby193",
     "gems_dir"=>"/opt/local/lib/ruby/gems/1.9.3",
     "gem_bin"=>"/opt/local/bin/gem193"}},
 "kernel"=>
  {"name"=>"SunOS",
   "release"=>"5.11",
   "version"=>"joyent_20130226T234312Z",
   "machine"=>"i86pc",
   "modules"=>{}},
 "os"=>"solaris2",
 "os_version"=>"5.11",
 "platform_version"=>"5.11",
 "platform_build"=>"joyent_20130226T234312Z",
 "platform"=>"smartos",
 "platform_family"=>"smartos"}
Irb-Out
> ohai.data[:platform]
=> "smartos"

判定OK。

Platformから利用するProviderを選択する(課題 => 解決)

これどうしたら良いのかしら、Chefのソースを追う課題として置いときます。

追記:解決しました
ohaiのデータを元に、ChefのProvidersを自動選択してcurrent_resourceをゲット

Providerを使ってCurrentResourceを取ってみる

気を取り直して、service[redis]が起動しているかをチェックしてみましょう。
必要なオブジェクトを適当にinitializeしていきます。

run_contextを作る

Irc-Out
> node = Chef::Node.new
=> node[]

> events = Chef::EventDispatch::Dispatcher.new
=> #<Chef::EventDispatch::Dispatcher:0x00000002ab2460 @subscribers=[]>

> run_context = Chef::RunContext.new(node, {}, events)
=> #<Chef::RunContext:0x00000001a72398
 @cookbook_collection={},
 @definitions={},
 @delayed_notification_collection={},
 @events=#<Chef::EventDispatch::Dispatcher:0x00000002ab2460 @subscribers=[]>,
 @immediate_notification_collection={},
 @loaded_attributes={},
 @loaded_recipes={},
 @node=node[],
 @resource_collection=
  #<Chef::ResourceCollection:0x00000001a723e8
   @insert_after_idx=nil,
   @resources=[],
   @resources_by_name={}>>

newとcurrentのresourceを作る

いわゆるservice[redis]リソースを作ります、Chef::Resource::Serviceのインスタンスですね。

Irc-Out
> new_resource = Chef::Resource::Service.new('redis')
=> <service[redis] @name: "redis" @noop: nil @before: nil @params: {} @provider: nil @allowed_actions: [:nothing, :enable, :disable, :start, :stop, :restart, :reload] @action: "nothing" @updated: false @updated_by_last_action: false @supports: {:restart=>false, :reload=>false, :status=>false} @ignore_failure: false @retries: 0 @retry_delay: 2 @source_line: nil @elapsed_time: 0 @resource_name: :service @service_name: "redis" @enabled: nil @running: nil @parameters: nil @pattern: "redis" @start_command: nil @stop_command: nil @status_command: nil @restart_command: nil @reload_command: nil @init_command: nil @priority: nil @startup_type: :automatic>

> current_resource = Chef::Resource::Service.new('redis')
=> <service[redis] @name: "redis" @noop: nil @before: nil @params: {} @provider: nil @allowed_actions: [:nothing, :enable, :disable, :start, :stop, :restart, :reload] @action: "nothing" @updated: false @updated_by_last_action: false @supports: {:restart=>false, :reload=>false, :status=>false} @ignore_failure: false @retries: 0 @retry_delay: 2 @source_line: nil @elapsed_time: 0 @resource_name: :service @service_name: "redis" @enabled: nil @running: nil @parameters: nil @pattern: "redis" @start_command: nil @stop_command: nil @status_command: nil @restart_command: nil @reload_command: nil @init_command: nil @priority: nil @startup_type: :automatic>

Providersを指定する

リソースを取得するためのプロバイダを作成します、今回はChef::Provider::Service::Solarisを指定します。
これをohaiの結果と連動したいところです。

Irc-Out
> provider = Chef::Provider::Service::Solaris.new(new_resource, run_context)
=> #<Chef::Provider::Service::Solaris:0x000000018d6020
 @action=nil,
 @converge_actions=nil,
 @current_resource=nil,
 @enabled=nil,
 @init_command="/usr/sbin/svcadm",
 @new_resource=
  <service[redis] @name: "redis" @noop: nil @before: nil @params: {} @provider: nil @allowed_actions: [:nothing, :enable, :disable, :start, :stop, :restart, :reload] @action: "nothing" @updated: false @updated_by_last_action: false @supports: {:restart=>false, :reload=>false, :status=>false} @ignore_failure: false @retries: 0 @retry_delay: 2 @source_line: nil @elapsed_time: 0 @resource_name: :service @service_name: "redis" @enabled: nil @running: nil @parameters: nil @pattern: "redis" @start_command: nil @stop_command: nil @status_command: nil @restart_command: nil @reload_command: nil @init_command: nil @priority: nil @startup_type: :automatic>,
 @run_context=
  #<Chef::RunContext:0x00000001a72398
   @cookbook_collection={},
   @definitions={},
   @delayed_notification_collection={},
   @events=#<Chef::EventDispatch::Dispatcher:0x00000002ab2460 @subscribers=[]>,
   @immediate_notification_collection={},
   @loaded_attributes={},
   @loaded_recipes={},
   @node=node[],
   @resource_collection=
    #<Chef::ResourceCollection:0x00000001a723e8
     @insert_after_idx=nil,
     @resources=[],
     @resources_by_name={}>>,
 @status_command="/bin/svcs -l">

Solarisらしくなってきました。

CurrentResourceの状態をチェックする

では締めに、service[redis]current_resourceを採取します。

Irc-Out
> provider.load_current_resource
=> <service[redis] @name: "redis" @noop: nil @before: nil @params: {} @provider: nil @allowed_actions: [:nothing, :enable, :disable, :start, :stop, :restart, :reload] @action: "nothing" @updated: false @updated_by_last_action: false @supports: {:restart=>false, :reload=>false, :status=>false} @ignore_failure: false @retries: 0 @retry_delay: 2 @source_line: nil @elapsed_time: 0 @resource_name: :service @service_name: "redis" @enabled: true @running: true @parameters: nil @pattern: "redis" @start_command: nil @stop_command: nil @status_command: nil @restart_command: nil @reload_command: nil @init_command: nil @priority: nil @startup_type: :automatic>

> provider.load_current_resource.enabled
=> true

取れました、これならChefとOhaiの資産が活用できそうです。load_current_resourceに文句があったらChefにプルリクすれば済むわけで。

RSpec的にチェックしたい場合

ヘルパーで色々やらせて、こんな感じでSpecに起こせればいい感じにサーバの受け入れテストが書けそうです。

expect(service[hogehoge].load_current_resource.enabled).to be_true

早いうちに残課題のProviders選択の所を追いたいですね。

追記:Providers解決しました
ohaiのデータを元に、ChefのProvidersを自動選択してcurrent_resourceをゲット

8
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8