LoginSignup
35
34

More than 5 years have passed since last update.

itamae resourceの書き方

Last updated at Posted at 2014-10-20

itamaeは軽量でChefライクなサーバ構成管理ツールです。詳しくはこちら
本稿ではitamaeで独自のresourceを定義する方法を紹介します。

resourceとは

文字通りサーバが持つ各リソースの種類に対応していて、itamaeではレシピにresourceを列挙することによってサーバの状態を定義します。
itamaeにはresource pluginを定義するための機構があり、簡単に独自のresourceを定義することができます。

plugin機構の仕組み

レシピのmethod_missingItamae::Plugin::Resource::*が探される

レシピに

foo "bar" do
  # ...
end

と書くと、レシピのmethod_missingItamae::Plugin::Resource::Fooが探されます
itamaeのレシピが読み込まれた段階でこのFoo resourceがレシピのchildrenに追加されます。

そのため、bundle gemの自動生成規則に従うと、pluginのgem名はitamae-plugin-resource-fooにする必要があります。

レシピに追加されたresourceがrunされる

レシピの読み込みが終わると、レシピに追加された各resourceがrunされます。
なので、

resource = Itamae::Plugin::Resource::Foo.new(recipe, "bar", &block)
resource.run(nil, dry_run: options[:dry_run])

が実行されたらサーバの状態に応じた適切なコマンドが走るようにItamae::Plugin::Resource::Fooを定義すればよいことになります。
resourceに共通して必要なメソッドがItamae::Resource::Baseに定義されているので、新たにresourceを定義するときはこれを継承し、必要な部分をオーバーライドする必要があります。

Itamae::Resource::Baseの仕組み

実際に定義するとなるとitamae/resource/base.rbをちゃんと読む必要がありますが、ここでは概要だけ説明します。

  • #newでresourceにaction等のattributeがセットされる
    • attributeは、ブロックの内側で使えるメソッドで、これがリソースの状態になる
    • define_attributeを列挙することで任意のパラメータを追加できる
  • #runでattributeに応じたコマンドを実行する
    • pre_action, set_current_attributes, show_differencesが順番に呼ばれる
    • :action attributeに応じたaction_#{action}が呼ばれる

従って、以下の3つの変更を行えばよいことになります。

  • define_attributeの列挙
  • pre_action, set_current_attributes, show_differencesのオーバーライド
  • action_#{action}メソッドの作成

作成例: ghq resource

例として、ghqを使ってgoの流儀に従ったリポジトリ配置を行うためのリソースを作成しました。
主にgit resourcemercurial resourceを参考に作りました。

k0kubun/itamae-plugin-resource-ghq

require "itamae/resource/base"

module Itamae
  module Plugin
    module Resource
      class Ghq < Itamae::Resource::Base
        define_attribute :action, default: :create
        define_attribute :repository, type: String, default_name: true

        def set_current_attributes
          ensure_ghq_availability

          result = run_command("ghq list | grep '#{attributes.repository}$'", error: false)
          current.exist = result.exit_status == 0
        end

        def action_create(options)
          unless current.exist
            run_command(["ghq", "get", attributes.repository])
          end
        end

        def action_update(options)
          result = run_command(["ghq", "get", "-u", attributes.repository])
          unless result.stdout.match(/is up to date/)
            updated!
          end
        end

        private

        def ensure_ghq_availability
          if run_command("which ghq", error: false).exit_status != 0
            raise "`ghq` command is not available. Please install ghq."
          end
        end
      end
    end
  end
end

すると、以下のように使えるようになります。

require "itamae/plugin/resource/ghq"

# ghq get ryotarai/itamae
ghq "ryotarai/itamae"

# ghq get -u serverspec/specinfra
ghq "serverspec/specinfra" do
  action :update
end
35
34
0

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
35
34