Class: RightScale::ExecutableSequence

Inherits:
Object
  • Object
show all
Includes:
Chef::Mixin::PathSanity, EM::Deferrable
Defined in:
lib/instance/cook/executable_sequence.rb

Overview

Bundle sequence, includes installing dependent packages, downloading attachments and running scripts in given bundle. Also downloads cookbooks and run recipes in given bundle. Runs in separate (runner) process.

Constant Summary collapse

OHAI_RETRY_MIN_DELAY =

Min number of seconds to wait before retrying Ohai to get the hostname

20
OHAI_RETRY_MAX_DELAY =

Max number of seconds to wait before retrying Ohai to get the hostname

20 * 60
BACKTRACE_LINE_REGEXP =

Regexp to use when reporting extended information about Chef failures (line-number, etc)

/(.+):(\d+):in `(.+)'/
AUDIT_BEGIN_OPERATIONS =
Set.new([:scraping]).freeze
AUDIT_COMMIT_OPERATIONS =
Set.new([:initialize,
:retrieving,
:reading_cookbook,
:scraping]).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bundle) ⇒ ExecutableSequence

Initialize sequence

Parameter

bundle(RightScale::ExecutableBundle)

Bundle to be run



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/instance/cook/executable_sequence.rb', line 72

def initialize(bundle)
  @description            = bundle.to_s
  @thread_name            = get_thread_name_from_bundle(bundle)
  @right_scripts_cookbook = RightScriptsCookbook.new(@thread_name)
  @scripts                = bundle.executables.select { |e| e.is_a?(RightScriptInstantiation) }
  run_list_recipes        = bundle.executables.map { |e| e.is_a?(RecipeInstantiation) ? e : @right_scripts_cookbook.recipe_from_right_script(e) }
  @cookbooks              = bundle.cookbooks
  @downloader             = ReposeDownloader.new(bundle.repose_servers)
  @downloader.logger      = Log
  @download_path          = File.join(AgentConfig.cookbook_download_dir, @thread_name)
  @powershell_providers   = nil
  @ohai_retry_delay       = OHAI_RETRY_MIN_DELAY
  @audit                  = AuditStub.instance
  @logger                 = Log
  @cookbook_repo_retriever= CookbookRepoRetriever.new(@download_path, bundle.dev_cookbooks)

  # Initialize run list for this sequence (partial converge support)
  @run_list  = []
  @inputs    = { }
  breakpoint = CookState.breakpoint
  run_list_recipes.each do |recipe|
    if recipe.nickname == breakpoint
      @audit.append_info("Breakpoint set to < #{breakpoint} >")
      break
    end
    @run_list << recipe.nickname
    ::RightSupport::Data::HashTools.deep_merge!(@inputs, recipe.attributes)
  end

  # Retrieve node attributes and deep merge in inputs
  @attributes = ChefState.attributes
  ::RightSupport::Data::HashTools.deep_merge!(@attributes, @inputs)
end

Instance Attribute Details

#failure_messageObject (readonly)

Failure title and message if any



66
67
68
# File 'lib/instance/cook/executable_sequence.rb', line 66

def failure_message
  @failure_message
end

#failure_titleObject (readonly)

Failure title and message if any



66
67
68
# File 'lib/instance/cook/executable_sequence.rb', line 66

def failure_title
  @failure_title
end

#inputs_patchObject

Patch to be applied to inputs stored in core



63
64
65
# File 'lib/instance/cook/executable_sequence.rb', line 63

def inputs_patch
  @inputs_patch
end

Instance Method Details

#get_policy_name_from_bundle(bundle) ⇒ Object

FIX: This code can be removed once the core sends a runlist policy

Parameters

bundle(ExecutableBundle)

An executable bundle

Return

result(String)

Policy name of this bundle



135
136
137
138
139
# File 'lib/instance/cook/executable_sequence.rb', line 135

def get_policy_name_from_bundle(bundle)
  policy_name = nil
  policy_name ||= bundle.runlist_policy.policy_name if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy
  policy_name
end

#get_thread_name_from_bundle(bundle) ⇒ Object

FIX: thread_name should never be nil from the core in future, but temporarily we must supply the default thread_name before if nil. in future we should fail execution when thread_name is reliably present and for any reason does not match ::RightScale::AgentConfig.valid_thread_name see also ExecutableSequenceProxy#initialize

Parameters

bundle(ExecutableBundle)

An executable bundle

Return

result(String)

Thread name of this bundle



117
118
119
120
121
122
123
124
125
126
# File 'lib/instance/cook/executable_sequence.rb', line 117

def get_thread_name_from_bundle(bundle)
  thread_name = nil
  thread_name = bundle.runlist_policy.thread_name if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy
  Log.warn("Encountered a nil thread name unexpectedly, defaulting to '#{RightScale::AgentConfig.default_thread_name}'") unless thread_name
  thread_name ||= RightScale::AgentConfig.default_thread_name
  unless thread_name =~ RightScale::AgentConfig.valid_thread_name
    raise ArgumentError, "Invalid thread name #{thread_name.inspect}"
  end
  thread_name
end

#runObject

Run given executable bundle Asynchronous, set deferrable object’s disposition

Return

true

Always return true



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/instance/cook/executable_sequence.rb', line 146

def run
  @ok = true
  if @run_list.empty?
    # Deliberately avoid auditing anything since we did not run any recipes
    # Still download the cookbooks repos if in dev mode
    checkout_cookbook_repos
    download_cookbooks if CookState.cookbooks_path
    report_success(nil)
  else
    configure_ohai
    configure_logging
    configure_chef
    download_attachments if @ok
    install_packages if @ok
    checkout_cookbook_repos if @ok
    download_cookbooks if @ok
    update_cookbook_path if @ok
    setup_powershell_providers if RightScale::Platform.windows?

    # note that chef normally enforces path sanity before executing ohai in
    # the client run method. we create ohai before client run and some ohai
    # plugins behave badly when there is no ruby on the PATH. we need to do
    # a pre-emptive path sanity here before we start ohai and chef.
    enforce_path_sanity
    check_ohai { |o| converge(o) } if @ok
  end
  true
rescue Exception => e
  report_failure('Execution failed', "The following exception was caught while preparing for execution: (#{e.message}) from\n#{e.backtrace.join("\n")}")
end