itamae 1.0.0.beta26 → 1.0.0.beta27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/lib/itamae.rb +2 -1
- data/lib/itamae/notification.rb +23 -0
- data/lib/itamae/recipe.rb +27 -20
- data/lib/itamae/recipe_children.rb +61 -0
- data/lib/itamae/resource/base.rb +18 -31
- data/lib/itamae/runner.rb +14 -5
- data/lib/itamae/version.txt +1 -1
- data/spec/integration/default_spec.rb +4 -0
- data/spec/integration/recipes/default.rb +6 -0
- data/spec/integration/recipes/default2.rb +6 -0
- data/spec/unit/lib/itamae/runner_spec.rb +1 -0
- metadata +6 -3
- data/lib/itamae/recipe_dependencies.rb +0 -39
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f71dbe4da1c49cacda9dac2d10c5c1cb0263e6b4
         | 
| 4 | 
            +
              data.tar.gz: 09480bb0d8624135546598f390cabd30428b8ce0
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 4238df2db65e2f9a66d5a0021d724e0e1d1f2234f97b62b4e3fab49f8560e92150124221b2a755f450cf782a919e3ad121ae3a8179021eaeba59eaed9fb08d18
         | 
| 7 | 
            +
              data.tar.gz: ada64866b96afadc1f916e3a4b106e9e4f59acc8c01e5797e6c86f26988a5b6af207d97de8d09e5ee25816c8e31ad4ad6b49f4abcafe4bbb54395e3c5110ca0f
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/itamae.rb
    CHANGED
    
    | @@ -3,10 +3,11 @@ require "itamae/runner" | |
| 3 3 | 
             
            require "itamae/cli"
         | 
| 4 4 | 
             
            require "itamae/recipe"
         | 
| 5 5 | 
             
            require "itamae/resource"
         | 
| 6 | 
            -
            require "itamae/ | 
| 6 | 
            +
            require "itamae/recipe_children"
         | 
| 7 7 | 
             
            require "itamae/logger"
         | 
| 8 8 | 
             
            require "itamae/node"
         | 
| 9 9 | 
             
            require "itamae/backend"
         | 
| 10 | 
            +
            require "itamae/notification"
         | 
| 10 11 |  | 
| 11 12 | 
             
            module Itamae
         | 
| 12 13 | 
             
              # Your code goes here...
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'itamae'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Itamae
         | 
| 4 | 
            +
              class Notification < Struct.new(:runner, :defined_in_resource, :action, :target_resource_desc, :timing)
         | 
| 5 | 
            +
                def resource
         | 
| 6 | 
            +
                  runner.children.find_resource_by_description(target_resource_desc)
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def run(options)
         | 
| 10 | 
            +
                  action_resource.run(action, options)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def action_resource
         | 
| 14 | 
            +
                  resource
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              class Subscription < Notification
         | 
| 19 | 
            +
                def action_resource
         | 
| 20 | 
            +
                  defined_in_resource
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
    
        data/lib/itamae/recipe.rb
    CHANGED
    
    | @@ -2,18 +2,20 @@ require 'itamae' | |
| 2 2 |  | 
| 3 3 | 
             
            module Itamae
         | 
| 4 4 | 
             
              class Recipe
         | 
| 5 | 
            +
                NotFoundError = Class.new(StandardError)
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
                attr_reader :path
         | 
| 6 8 | 
             
                attr_reader :runner
         | 
| 7 | 
            -
                attr_reader : | 
| 8 | 
            -
                attr_reader : | 
| 9 | 
            +
                attr_reader :children
         | 
| 10 | 
            +
                attr_reader :delayed_notifications
         | 
| 9 11 |  | 
| 10 12 | 
             
                def initialize(runner, path)
         | 
| 11 13 | 
             
                  @runner = runner
         | 
| 12 14 | 
             
                  @path = path
         | 
| 13 | 
            -
                  @ | 
| 14 | 
            -
                  @ | 
| 15 | 
            +
                  @children = RecipeChildren.new
         | 
| 16 | 
            +
                  @delayed_notifications = []
         | 
| 15 17 |  | 
| 16 | 
            -
                   | 
| 18 | 
            +
                  load_children
         | 
| 17 19 | 
             
                end
         | 
| 18 20 |  | 
| 19 21 | 
             
                def node
         | 
| @@ -21,19 +23,14 @@ module Itamae | |
| 21 23 | 
             
                end
         | 
| 22 24 |  | 
| 23 25 | 
             
                def run(options = {})
         | 
| 24 | 
            -
                  Logger.info " | 
| 25 | 
            -
             | 
| 26 | 
            -
                  @dependencies.each do |resource|
         | 
| 27 | 
            -
                    case resource
         | 
| 28 | 
            -
                    when Resource::Base
         | 
| 29 | 
            -
                      resource.run(nil, dry_run: options[:dry_run])
         | 
| 30 | 
            -
                    when Recipe
         | 
| 31 | 
            -
                      resource.run(options)
         | 
| 32 | 
            -
                    end
         | 
| 33 | 
            -
                  end
         | 
| 26 | 
            +
                  Logger.info "Recipe: #{@path}"
         | 
| 34 27 |  | 
| 35 | 
            -
                  @ | 
| 36 | 
            -
             | 
| 28 | 
            +
                  @children.run(options)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  @delayed_notifications.uniq do |notification|
         | 
| 31 | 
            +
                    [notification.action, notification.action_resource]
         | 
| 32 | 
            +
                  end.each do |notification|
         | 
| 33 | 
            +
                    notification.run(options)
         | 
| 37 34 | 
             
                  end
         | 
| 38 35 |  | 
| 39 36 | 
             
                  Logger.info "< Finished. (#{@path})"
         | 
| @@ -41,22 +38,32 @@ module Itamae | |
| 41 38 |  | 
| 42 39 | 
             
                private
         | 
| 43 40 |  | 
| 44 | 
            -
                def  | 
| 41 | 
            +
                def load_children
         | 
| 45 42 | 
             
                  instance_eval(File.read(@path), @path, 1)
         | 
| 46 43 | 
             
                end
         | 
| 47 44 |  | 
| 48 45 | 
             
                def method_missing(method, name, &block)
         | 
| 49 46 | 
             
                  klass = Resource.get_resource_class(method)
         | 
| 50 47 | 
             
                  resource = klass.new(self, name, &block)
         | 
| 51 | 
            -
                  @ | 
| 48 | 
            +
                  @children << resource
         | 
| 52 49 | 
             
                rescue NameError
         | 
| 53 50 | 
             
                  super
         | 
| 54 51 | 
             
                end
         | 
| 55 52 |  | 
| 56 53 | 
             
                def include_recipe(target)
         | 
| 57 54 | 
             
                  target = ::File.expand_path(target, File.dirname(@path))
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  unless File.exist?(target)
         | 
| 57 | 
            +
                    raise NotFoundError, "File not found. (#{target})"
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  if runner.children.find_recipe_by_path(target)
         | 
| 61 | 
            +
                    Logger.debug "Recipe, #{target}, is skipped because it is already included"
         | 
| 62 | 
            +
                    return
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 58 65 | 
             
                  recipe = Recipe.new(@runner, target)
         | 
| 59 | 
            -
                  @ | 
| 66 | 
            +
                  @children << recipe
         | 
| 60 67 | 
             
                end
         | 
| 61 68 | 
             
              end
         | 
| 62 69 | 
             
            end
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            module Itamae
         | 
| 2 | 
            +
              class RecipeChildren < Array
         | 
| 3 | 
            +
                NotFoundError = Class.new(StandardError)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def find_resource_by_description(desc)
         | 
| 6 | 
            +
                  # desc is like 'resource_type[name]'
         | 
| 7 | 
            +
                  resources.find do |resource|
         | 
| 8 | 
            +
                    type, name = Itamae::Resource.parse_description(desc)
         | 
| 9 | 
            +
                    resource.resource_type == type && resource.resource_name == name
         | 
| 10 | 
            +
                  end.tap do |resource|
         | 
| 11 | 
            +
                    unless resource
         | 
| 12 | 
            +
                      raise NotFoundError, "'#{desc}' resource is not found."
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def subscribing(target)
         | 
| 18 | 
            +
                  resources.map do |resource|
         | 
| 19 | 
            +
                    resource.subscriptions.select do |subscription|
         | 
| 20 | 
            +
                      subscription.resource == target
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end.flatten
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def find_recipe_by_path(path)
         | 
| 26 | 
            +
                  recipes.find do |recipe|
         | 
| 27 | 
            +
                    recipe.path == path
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def resources
         | 
| 32 | 
            +
                  self.map do |item|
         | 
| 33 | 
            +
                    case item
         | 
| 34 | 
            +
                    when Resource::Base
         | 
| 35 | 
            +
                      item
         | 
| 36 | 
            +
                    when Recipe
         | 
| 37 | 
            +
                      item.children.resources
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end.flatten
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def recipes
         | 
| 43 | 
            +
                  self.select do |item|
         | 
| 44 | 
            +
                    item.is_a?(Recipe)
         | 
| 45 | 
            +
                  end.map do |recipe|
         | 
| 46 | 
            +
                    [recipe] + recipe.children.recipes
         | 
| 47 | 
            +
                  end.flatten
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def run(options)
         | 
| 51 | 
            +
                  self.each do |resource|
         | 
| 52 | 
            +
                    case resource
         | 
| 53 | 
            +
                    when Resource::Base
         | 
| 54 | 
            +
                      resource.run(nil, dry_run: options[:dry_run])
         | 
| 55 | 
            +
                    when Recipe
         | 
| 56 | 
            +
                      resource.run(options)
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
    
        data/lib/itamae/resource/base.rb
    CHANGED
    
    | @@ -30,14 +30,16 @@ module Itamae | |
| 30 30 | 
             
                  attr_reader :resource_name
         | 
| 31 31 | 
             
                  attr_reader :attributes
         | 
| 32 32 | 
             
                  attr_reader :current_attributes
         | 
| 33 | 
            +
                  attr_reader :subscriptions
         | 
| 34 | 
            +
                  attr_reader :notifications
         | 
| 33 35 |  | 
| 34 36 | 
             
                  def initialize(recipe, resource_name, &block)
         | 
| 35 37 | 
             
                    @attributes = {}
         | 
| 36 38 | 
             
                    @current_attributes = {}
         | 
| 37 39 | 
             
                    @recipe = recipe
         | 
| 38 40 | 
             
                    @resource_name = resource_name
         | 
| 39 | 
            -
                    @ | 
| 40 | 
            -
                    @ | 
| 41 | 
            +
                    @notifications = []
         | 
| 42 | 
            +
                    @subscriptions = []
         | 
| 41 43 | 
             
                    @updated = false
         | 
| 42 44 |  | 
| 43 45 | 
             
                    instance_eval(&block) if block_given?
         | 
| @@ -46,13 +48,13 @@ module Itamae | |
| 46 48 | 
             
                  end
         | 
| 47 49 |  | 
| 48 50 | 
             
                  def run(specific_action = nil, options = {})
         | 
| 49 | 
            -
                    Logger.info " | 
| 51 | 
            +
                    Logger.info "Executing #{resource_type} (#{attributes})..."
         | 
| 50 52 |  | 
| 51 53 | 
             
                    if do_not_run_because_of_only_if?
         | 
| 52 | 
            -
                      Logger.info " | 
| 54 | 
            +
                      Logger.info "Execution skipped because of only_if attribute"
         | 
| 53 55 | 
             
                      return
         | 
| 54 56 | 
             
                    elsif do_not_run_because_of_not_if?
         | 
| 55 | 
            -
                      Logger.info " | 
| 57 | 
            +
                      Logger.info "Execution skipped because of not_if attribute"
         | 
| 56 58 | 
             
                      return
         | 
| 57 59 | 
             
                    end
         | 
| 58 60 |  | 
| @@ -69,11 +71,12 @@ module Itamae | |
| 69 71 |  | 
| 70 72 | 
             
                    updated! if different?
         | 
| 71 73 |  | 
| 72 | 
            -
                    notify if updated?
         | 
| 74 | 
            +
                    notify(options) if updated?
         | 
| 73 75 |  | 
| 74 | 
            -
                    Logger.info " | 
| 76 | 
            +
                    Logger.info "Succeeded."
         | 
| 77 | 
            +
                    Logger.info ''
         | 
| 75 78 | 
             
                  rescue Backend::CommandExecutionError
         | 
| 76 | 
            -
                    Logger.error " | 
| 79 | 
            +
                    Logger.error "Failed."
         | 
| 77 80 | 
             
                    exit 2
         | 
| 78 81 | 
             
                  end
         | 
| 79 82 |  | 
| @@ -93,21 +96,6 @@ module Itamae | |
| 93 96 | 
             
                    humps.join('_')
         | 
| 94 97 | 
             
                  end
         | 
| 95 98 |  | 
| 96 | 
            -
                  def notifies_resources
         | 
| 97 | 
            -
                    @notifies.map do |action, resource_desc, timing|
         | 
| 98 | 
            -
                      resource = recipe.dependencies.find_by_description(resource_desc)
         | 
| 99 | 
            -
                      [action, resource, timing]
         | 
| 100 | 
            -
                    end
         | 
| 101 | 
            -
                  end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                  def subscribes_resources
         | 
| 104 | 
            -
                    @subscribes.map do |action, resource_desc, timing|
         | 
| 105 | 
            -
                      resource = recipe.dependencies.find_by_description(resource_desc)
         | 
| 106 | 
            -
                      [action, resource, timing]
         | 
| 107 | 
            -
                    end
         | 
| 108 | 
            -
                  end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 99 | 
             
                  private
         | 
| 112 100 |  | 
| 113 101 | 
             
                  def method_missing(method, *args, &block)
         | 
| @@ -200,11 +188,11 @@ module Itamae | |
| 200 188 | 
             
                  end
         | 
| 201 189 |  | 
| 202 190 | 
             
                  def notifies(action, resource_desc, timing = :delay)
         | 
| 203 | 
            -
                    @ | 
| 191 | 
            +
                    @notifications << Notification.new(runner, self, action, resource_desc, timing)
         | 
| 204 192 | 
             
                  end
         | 
| 205 193 |  | 
| 206 194 | 
             
                  def subscribes(action, resource_desc, timing = :delay)
         | 
| 207 | 
            -
                    @ | 
| 195 | 
            +
                    @subscriptions << Subscription.new(runner, self, action, resource_desc, timing)
         | 
| 208 196 | 
             
                  end
         | 
| 209 197 |  | 
| 210 198 | 
             
                  def node
         | 
| @@ -248,14 +236,13 @@ module Itamae | |
| 248 236 | 
             
                    @updated
         | 
| 249 237 | 
             
                  end
         | 
| 250 238 |  | 
| 251 | 
            -
                  def notify
         | 
| 252 | 
            -
                     | 
| 253 | 
            -
             | 
| 254 | 
            -
                      case timing
         | 
| 239 | 
            +
                  def notify(options)
         | 
| 240 | 
            +
                    (notifications + recipe.children.subscribing(self)).each do |notification|
         | 
| 241 | 
            +
                      case notification.timing
         | 
| 255 242 | 
             
                      when :immediately
         | 
| 256 | 
            -
                         | 
| 243 | 
            +
                        notification.run(options)
         | 
| 257 244 | 
             
                      when :delay
         | 
| 258 | 
            -
                        @recipe. | 
| 245 | 
            +
                        @recipe.delayed_notifications << notification
         | 
| 259 246 | 
             
                      end
         | 
| 260 247 | 
             
                    end
         | 
| 261 248 | 
             
                  end
         | 
    
        data/lib/itamae/runner.rb
    CHANGED
    
    | @@ -10,11 +10,8 @@ module Itamae | |
| 10 10 | 
             
                    set_backend_from_options(backend_type, options)
         | 
| 11 11 |  | 
| 12 12 | 
             
                    runner = self.new(node_from_options(options))
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                     | 
| 15 | 
            -
                      recipe = Recipe.new(runner, File.expand_path(path))
         | 
| 16 | 
            -
                      recipe.run(dry_run: options[:dry_run])
         | 
| 17 | 
            -
                    end
         | 
| 13 | 
            +
                    runner.load_recipes(recipe_files)
         | 
| 14 | 
            +
                    runner.run(dry_run: options[:dry_run])
         | 
| 18 15 | 
             
                  end
         | 
| 19 16 |  | 
| 20 17 | 
             
                  private
         | 
| @@ -60,14 +57,26 @@ module Itamae | |
| 60 57 |  | 
| 61 58 | 
             
                attr_accessor :node
         | 
| 62 59 | 
             
                attr_accessor :tmpdir
         | 
| 60 | 
            +
                attr_accessor :children
         | 
| 63 61 |  | 
| 64 62 | 
             
                def initialize(node)
         | 
| 65 63 | 
             
                  @node = node
         | 
| 66 64 | 
             
                  @tmpdir = "/tmp/itamae_tmp"
         | 
| 65 | 
            +
                  @children = RecipeChildren.new
         | 
| 67 66 |  | 
| 68 67 | 
             
                  Backend.instance.run_command(["mkdir", "-p", @tmpdir])
         | 
| 69 68 | 
             
                  Backend.instance.run_command(["chmod", "777", @tmpdir])
         | 
| 70 69 | 
             
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def load_recipes(paths)
         | 
| 72 | 
            +
                  paths.each do |path|
         | 
| 73 | 
            +
                    children << Recipe.new(self, File.expand_path(path))
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                def run(options)
         | 
| 78 | 
            +
                  children.run(options)
         | 
| 79 | 
            +
                end
         | 
| 71 80 | 
             
              end
         | 
| 72 81 | 
             
            end
         | 
| 73 82 |  | 
    
        data/lib/itamae/version.txt
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            1.0.0. | 
| 1 | 
            +
            1.0.0.beta27
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: itamae
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0.0. | 
| 4 | 
            +
              version: 1.0.0.beta27
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ryota Arai
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014-08- | 
| 11 | 
            +
            date: 2014-08-25 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: thor
         | 
| @@ -158,8 +158,9 @@ files: | |
| 158 158 | 
             
            - lib/itamae/cli.rb
         | 
| 159 159 | 
             
            - lib/itamae/logger.rb
         | 
| 160 160 | 
             
            - lib/itamae/node.rb
         | 
| 161 | 
            +
            - lib/itamae/notification.rb
         | 
| 161 162 | 
             
            - lib/itamae/recipe.rb
         | 
| 162 | 
            -
            - lib/itamae/ | 
| 163 | 
            +
            - lib/itamae/recipe_children.rb
         | 
| 163 164 | 
             
            - lib/itamae/resource.rb
         | 
| 164 165 | 
             
            - lib/itamae/resource/base.rb
         | 
| 165 166 | 
             
            - lib/itamae/resource/directory.rb
         | 
| @@ -180,6 +181,7 @@ files: | |
| 180 181 | 
             
            - spec/integration/Vagrantfile
         | 
| 181 182 | 
             
            - spec/integration/default_spec.rb
         | 
| 182 183 | 
             
            - spec/integration/recipes/default.rb
         | 
| 184 | 
            +
            - spec/integration/recipes/default2.rb
         | 
| 183 185 | 
             
            - spec/integration/recipes/hello.erb
         | 
| 184 186 | 
             
            - spec/integration/recipes/hello.txt
         | 
| 185 187 | 
             
            - spec/integration/recipes/included.rb
         | 
| @@ -221,6 +223,7 @@ test_files: | |
| 221 223 | 
             
            - spec/integration/Vagrantfile
         | 
| 222 224 | 
             
            - spec/integration/default_spec.rb
         | 
| 223 225 | 
             
            - spec/integration/recipes/default.rb
         | 
| 226 | 
            +
            - spec/integration/recipes/default2.rb
         | 
| 224 227 | 
             
            - spec/integration/recipes/hello.erb
         | 
| 225 228 | 
             
            - spec/integration/recipes/hello.txt
         | 
| 226 229 | 
             
            - spec/integration/recipes/included.rb
         | 
| @@ -1,39 +0,0 @@ | |
| 1 | 
            -
            module Itamae
         | 
| 2 | 
            -
              class RecipeDependencies < Array
         | 
| 3 | 
            -
                NotFoundError = Class.new(StandardError)
         | 
| 4 | 
            -
             | 
| 5 | 
            -
                def find_by_description(desc)
         | 
| 6 | 
            -
                  # desc is like 'resource_type[name]'
         | 
| 7 | 
            -
                  resources.find do |resource|
         | 
| 8 | 
            -
                    type, name = Itamae::Resource.parse_description(desc)
         | 
| 9 | 
            -
                    resource.resource_type == type && resource.resource_name == name
         | 
| 10 | 
            -
                  end.tap do |resource|
         | 
| 11 | 
            -
                    unless resource
         | 
| 12 | 
            -
                      raise NotFoundError, "'#{desc}' resource is not found."
         | 
| 13 | 
            -
                    end
         | 
| 14 | 
            -
                  end
         | 
| 15 | 
            -
                end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                def subscribing(target)
         | 
| 18 | 
            -
                  resources.map do |resource|
         | 
| 19 | 
            -
                    resource.subscribes_resources.map do |action, r, timing|
         | 
| 20 | 
            -
                      if r == target
         | 
| 21 | 
            -
                        [action, resource, timing]
         | 
| 22 | 
            -
                      end
         | 
| 23 | 
            -
                    end.compact
         | 
| 24 | 
            -
                  end.flatten(1)
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                def resources
         | 
| 28 | 
            -
                  self.select do |item|
         | 
| 29 | 
            -
                    item.is_a?(Resource::Base)
         | 
| 30 | 
            -
                  end
         | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                def recipes
         | 
| 34 | 
            -
                  self.select do |item|
         | 
| 35 | 
            -
                    item.is_a?(Recipe)
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
              end
         | 
| 39 | 
            -
            end
         |