class MotherBrain::Gear::Service::ActionRunner

@api private

Attributes

environment[R]
environment_attributes[R]
node_attributes[R]
nodes[R]
service_recipe[R]
toggle_callbacks[R]

Public Class Methods

new(environment, nodes, &block) click to toggle source

@param [String] environment @param [Array<Ridley::Node>] nodes

# File lib/mb/gears/service/action_runner.rb, line 17
def initialize(environment, nodes, &block)
  @environment = environment
  @nodes       = Array(nodes)

  @environment_attributes = Array.new
  @node_attributes        = Array.new
  @toggle_callbacks       = Array.new

  if block_given?
    dsl_eval(&block)
  end
end

Public Instance Methods

add_environment_attribute(key, value, options = {}) click to toggle source

Set an environment level attribute to the given value. The key is represented by a dotted path.

@param [String] key @param [Object] value

@option options [Boolean] :toggle (false)

set this environment attribute only for a single chef run
# File lib/mb/gears/service/action_runner.rb, line 47
def add_environment_attribute(key, value, options = {})
  @environment_attributes << { key: key, value: value, options: options }
end
add_node_attribute(key, value, options) click to toggle source

Set a node level attribute on all nodes for this action to the given value. The key is represented by a dotted path.

@param [String] key @param [Object] value

@option options [Boolean] :toggle (false)

set this node attribute only for a single chef run
# File lib/mb/gears/service/action_runner.rb, line 59
def add_node_attribute(key, value, options)
  @node_attributes << { key: key, value: value, options: options }
end
reset(job) click to toggle source
# File lib/mb/gears/service/action_runner.rb, line 30
def reset(job)
  toggle_callbacks.concurrent_map { |callback| callback.call(job) }
end
run(job) click to toggle source
# File lib/mb/gears/service/action_runner.rb, line 34
def run(job)
  set_node_attributes(job)
  set_environment_attributes(job)
end
set_service_recipe(recipe) click to toggle source
# File lib/mb/gears/service/action_runner.rb, line 63
def set_service_recipe(recipe)
  @service_recipe = recipe
end

Private Instance Methods

dsl_eval(&block) click to toggle source
# File lib/mb/gears/service/action_runner.rb, line 69
def dsl_eval(&block)
  CleanRoom.new(self).instance_eval(&block)
end
set_environment_attributes(job) click to toggle source
# File lib/mb/gears/service/action_runner.rb, line 91
def set_environment_attributes(job)
  return unless environment_attributes.any?

  unless env_chef_object = ridley.environment.find(environment)
    raise MB::EnvironmentNotFound.new(environment)
  end

  environment_attributes.each do |attribute|
    key, value, options = attribute[:key], attribute[:value], attribute[:options]

    if options[:toggle]
      toggle_callbacks << ->(job) {
        message = "Toggling (removing) environment attribute '#{key}' on #{environment}"
        job.set_status(message)
        env_chef_object.delete_default_attribute(key)
        env_chef_object.save
      }
    end

    job.set_status("Setting environment attribute '#{key}' to #{value.inspect} in #{environment}")
    env_chef_object.set_default_attribute(key, value)
  end

  job.set_status("Saving environment #{environment}")
  env_chef_object.save
end
set_node_attributes(job) click to toggle source

Set all node level attributes to the given node

@param [Ridley::Job] job

a job to send status updates to

@param [Ridley::NodeObject] node

the node to set the attribute on
# File lib/mb/gears/service/action_runner.rb, line 124
def set_node_attributes(job)
  return if node_attributes.empty?

  nodes.concurrent_map do |node|
    node.reload

    node_attributes.each do |attribute|
      key, value, options = attribute[:key], attribute[:value], attribute[:options]

      if options[:toggle]
        original_value = node.chef_attributes.dig(key)

        toggle_callbacks << ->(job) {
          message = if original_value.nil?
            "Toggling off node attribute '#{key}' on #{node.name}"
          elsif !options[:force_value_to].nil?
            "Forcing node attribute to '#{options[:force_value_to]}' on #{node.name}"
          else
            "Toggling node attribute '#{key}' back to '#{original_value.inspect}' on #{node.name}"
          end
          job.set_status(message)
          value_to_set = options[:force_value_to].nil? ? original_value : options[:force_value_to]
          node.set_chef_attribute(key, value_to_set)
          node.save
        }
      end

      job.set_status("Setting node attribute '#{key}' to #{value.inspect} on #{node.name}")
      node.set_chef_attribute(key, value)
    end

    node.save
  end
end