Skip to content

Commit

Permalink
Add end to end lauching of Embedded Ansible via ansible-runner
Browse files Browse the repository at this point in the history
  • Loading branch information
Fryguy authored and NickLaMuro committed May 22, 2019
1 parent db2c372 commit 68170a6
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 2 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ gem "rugged", "~>0.27.0", :require => false
gem "snmp", "~>1.2.0", :require => false
gem "sqlite3", "~>1.3.0", :require => false
gem "sys-filesystem", "~>1.2.0"
gem "terminal", :require => false

# Modified gems (forked on Github)
gem "ruport", "=1.7.0", :git => "https://github.com/ManageIQ/ruport.git", :tag => "v1.7.0-3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,22 @@ def raw_update_in_provider(params)
def raw_delete_in_provider
destroy!
end

def run(vars = {})
options = vars.merge(merge_extra_vars(vars[:extra_vars]))

ManageIQ::Providers::AnsiblePlaybookWorkflow.create_job({}, options[:extra_vars], {:playbook_path => parent.path}).tap do |job|
job.signal(:start)
end
end

private

def merge_extra_vars(external)
extra_vars = variables.merge(external || {}).each_with_object({}) do |(k, v), hash|
match_data = v.kind_of?(String) && /password::/.match(v)
hash[k] = match_data ? ManageIQ::Password.decrypt(v.gsub(/password::/, '')) : v
end
{:extra_vars => extra_vars}
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ def sync
sync_playbooks
end

def path_to_playbook(playbook_name)
repo_dir.join(playbook_name)
end

private

def git(*params, chdir: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,81 @@ class ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Job < ManageIQ::P

require_nested :Status

belongs_to :ext_management_system, :foreign_key => :ems_id, :class_name => "ManageIQ::Providers::AutomationManager"
belongs_to :job_template, :foreign_key => :orchestration_template_id, :class_name => "ConfigurationScript"
belongs_to :playbook, :foreign_key => :configuration_script_base_id

belongs_to :miq_task, :foreign_key => :ems_ref

#
# Allowed options are
# :limit => String
# :extra_vars => Hash
#
def self.create_stack(template, options = {})
template_ref = template.new_record? ? nil : template
new(:name => template.name,
:ext_management_system => template.manager,
:job_template => template_ref).tap do |stack|
stack.send(:update_with_provider_object, raw_create_stack(template, options))
end
end

def self.raw_create_stack(template, options = {})
options = reconcile_extra_vars_keys(template, options)
template.run(options)
rescue => err
_log.error("Failed to create job from template(#{template.name}), error: #{err}")
raise MiqException::MiqOrchestrationProvisionError, err.to_s, err.backtrace
end

class << self
alias create_job create_stack
alias raw_create_job raw_create_stack
end

private def update_with_provider_object(raw_job)
self.miq_task ||= raw_job.miq_task

update_attributes!(
:status => miq_task.state,
:start_time => miq_task.started_on,
:finish_time => raw_status.completed? ? miq_task.updated_on : nil
)
end

def raw_status
Status.new(miq_task, nil)
end

def raw_stdout(format = 'txt')
case format
when "json" then raw_stdout_json
when "html" then raw_stdout_html
else raw_stdout_txt
end
end

private def raw_stdout_json
miq_task.context_data[:ansible_runner_stdout]
end

private def raw_stdout_txt
raw_stdout_json.collect { |j| j["stdout"] }.join("\n")
end

private def raw_stdout_html
TerminalToHtml.render(raw_stdout_txt)
end

def refresh_ems
update_with_provider_object(self)
end

def job_plays
[]
end

# Intend to be called by UI to display stdout. The stdout is stored in MiqTask#task_results or #message if error
# Since the task_results may contain a large block of data, it is desired to remove the task upon receiving the data
def raw_stdout_via_worker(userid, format = 'txt')
Expand All @@ -17,10 +92,29 @@ def raw_stdout_via_worker(userid, format = 'txt')
).id
end

super(userid, format, 'embedded_ansible')
options = {:userid => userid || 'system', :action => 'ansible_stdout'}
queue_options = {
:class_name => self.class,
:method_name => 'raw_stdout',
:instance_id => id,
:args => [format],
:priority => MiqQueue::HIGH_PRIORITY,
:role => nil
}

MiqTask.generic_action_with_callback(options, queue_options)
end

def retireable?
false
end

private

# If extra_vars are passed through automate, all keys are considered as attributes and
# converted to lower case. Need to convert them back to original definitions in the
# job template through survey_spec or variables
def self.reconcile_extra_vars_keys(template, options)
options
end
end
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
class ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Job::Status < ::OrchestrationStack::Status
alias miq_task status

def succeeded?
miq_task.state == MiqTask::STATE_FINISHED && miq_task.status == MiqTask::STATUS_OK
end

def failed?
miq_task.state == MiqTask::STATE_FINISHED && miq_task.status != MiqTask::STATUS_OK
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Playbook < ManageIQ::Providers::EmbeddedAutomationManager::ConfigurationScriptPayload
has_many :jobs, :class_name => 'OrchestrationStack', :foreign_key => :configuration_script_base_id

def path
configuration_script_source.path_to_playbook(name)
end

def run(options, userid = nil)
options[:playbook_id] = id
options[:userid] = userid || 'system'
Expand Down
2 changes: 1 addition & 1 deletion app/models/service_ansible_playbook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def update_job_for_playbook(action, job, hosts)
hosts = 'localhost' if use_default_inventory?(hosts)
host_array = hosts.split(',')
playbook_id = options.fetch_path(:config_info, action.downcase.to_sym, :playbook_id)
job.update_attributes(:configuration_script_base_id => playbook_id, :hosts => host_array)
job.update_attributes!(:configuration_script_base_id => playbook_id, :hosts => host_array)
end

def decrypt_options(opts)
Expand Down
24 changes: 24 additions & 0 deletions lib/terminal_to_html.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class TerminalToHtml
def self.render(raw)
wrap_html_container(raw_render(raw))
end

def self.raw_render(raw)
require "terminal"
Terminal.render(raw)
end

def self.wrap_html_container(rendered)
stylesheet = File.read(File.join(Gem.latest_spec_for("terminal").full_gem_path, "/app/assets/stylesheets/terminal.css"))
<<~EOHTML
<div>
<style scoped>
#{stylesheet.chomp}
</style>
<div class='term-container'>
#{rendered}
</div>
</div>
EOHTML
end
end

0 comments on commit 68170a6

Please sign in to comment.