Skip to content

Commit

Permalink
Merge pull request #78 from putmanoj/add-method-fetch-terraform-stdou…
Browse files Browse the repository at this point in the history
…t-for-ui

Add methods to fetch terraform stdout for showing in UI.
  • Loading branch information
agrare committed Oct 21, 2024
2 parents 6fd1b36 + 47707cc commit 4c66529
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,61 @@ def refresh
def raw_status
Status.new(miq_task)
end

# Intend to be called by UI to display stdout. The stdout is stored in TerraformRunner(api/stack#message)
def raw_stdout_via_worker(userid, format = 'txt')
unless MiqRegion.my_region.role_active?("embedded_terraform")
msg = "Cannot get standard output of this terraform-template because the embedded terraform role is not enabled"
return MiqTask.create(
:name => 'terraform_stdout',
:userid => userid || 'system',
:state => MiqTask::STATE_FINISHED,
:status => MiqTask::STATUS_ERROR,
:message => msg
).id
end

options = {:userid => userid || 'system', :action => 'terraform_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 raw_stdout(format = 'txt')
case format
when "html" then raw_stdout_html
else raw_stdout_txt
end
end

def raw_stdout_txt
data = terraform_runner_stack_data
data&.message
end

def raw_stdout_html
text = raw_stdout_txt
text = _("No output available") if text.blank?
TerminalToHtml.render(text)
end

private

def terraform_runner_stack_data
return if miq_task.nil? || miq_task.job.nil?

job = miq_task.job
terraform_stack_id = job.options[:terraform_stack_id]

return if terraform_stack_id.blank?

Terraform::Runner.fetch_result_by_stack_id(terraform_stack_id)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,161 @@
end
end
end

describe "#raw_stdout" do
let(:stack) { FactoryBot.create(:terraform_stack, :miq_task => miq_task) }
let(:template) { FactoryBot.create(:terraform_template) }

context "when miq_task.job present" do
let(:terraform_runner_url) { "https://1.2.3.4:7000" }
let(:hello_world_retrieve_response) do
require 'json'
JSON.parse(File.read(File.join(__dir__, "../../../../../lib/terraform/runner/data/responses/hello-world-retrieve-success.json")))
end
let(:miq_task) { FactoryBot.create(:miq_task, :job => job) }

let(:job) do
ManageIQ::Providers::EmbeddedTerraform::AutomationManager::Job.create_job(template, {}, {}, []).tap do |job|
job.state = "finished"
job.options = {
:terraform_stack_id => hello_world_retrieve_response['stack_id']
}
end
end

let(:terraform_runner_stdout) { hello_world_retrieve_response['message'] }
let(:terraform_runner_stdout_html) { TerminalToHtml.render(terraform_runner_stdout) }

before do
stub_const("ENV", ENV.to_h.merge("TERRAFORM_RUNNER_URL" => terraform_runner_url))

stub_request(:post, "#{terraform_runner_url}/api/stack/retrieve")
.with(:body => hash_including({:stack_id => hello_world_retrieve_response['stack_id']}))
.to_return(
:status => 200,
:body => hello_world_retrieve_response.to_json
)
end

it "json" do
expect(stack.raw_stdout("json")).to eq terraform_runner_stdout
end

it "txt" do
expect(stack.raw_stdout("txt")).to eq terraform_runner_stdout
end

it "html" do
expect(stack.raw_stdout("html")).to eq terraform_runner_stdout_html
end

it "nil" do
expect(stack.raw_stdout).to eq terraform_runner_stdout
end
end

shared_examples_for "terraform runner stdout not available from miq_task" do
it "json" do
expect(stack.raw_stdout("json")).to be_nil
end

it "txt" do
expect(stack.raw_stdout("txt")).to be_nil
end

it "html" do
expect(stack.raw_stdout("html")).to include <<~EOHTML
<div class='term-container'>
No output available
</div>
EOHTML
end

it "nil" do
expect(stack.raw_stdout).to be_nil
end
end

context "when miq_task is missing" do
let(:miq_task) { nil }

it_behaves_like "terraform runner stdout not available from miq_task"
end

context "when miq_task present, but missing miq_task.job" do
let(:miq_task) { FactoryBot.create(:miq_task, :job => nil) }

it_behaves_like "terraform runner stdout not available from miq_task"
end

context "when miq_task.job.options present but missing terraform_stack_id" do
let(:job) do
ManageIQ::Providers::EmbeddedTerraform::AutomationManager::Job.create_job(template, {}, {}, []).tap do |job|
job.state = "waiting_to_start"
job.options = {}
end
end

let(:miq_task) { FactoryBot.create(:miq_task, :job => job) }

it_behaves_like "terraform runner stdout not available from miq_task"
end
end

describe "#raw_stdout_via_worker" do
let(:stack) { FactoryBot.create(:terraform_stack) }

context "when embedded_terraform role is enabled" do
before do
EmbeddedTerraformEvmSpecHelper.assign_embedded_terraform_role

allow_any_instance_of(ManageIQ::Providers::EmbeddedTerraform::AutomationManager::ConfigurationScriptSource).to receive(:checkout_git_repository)
end

describe "#raw_stdout_via_worker with no errors" do
before do
EvmSpecHelper.local_miq_server
allow(described_class).to receive(:find).and_return(stack)

allow(MiqTask).to receive(:wait_for_taskid) do
request = MiqQueue.find_by(:class_name => described_class.name)
request.update(:state => MiqQueue::STATE_DEQUEUE)
request.deliver_and_process
end
end

it "gets stdout from the job" do
expect(stack).to receive(:raw_stdout).and_return("A stdout from the job")
taskid = stack.raw_stdout_via_worker("user")
MiqTask.wait_for_taskid(taskid)
expect(MiqTask.find(taskid)).to have_attributes(
:task_results => "A stdout from the job",
:status => "Ok"
)
end

it "returns the error message" do
expect(stack).to receive(:raw_stdout).and_throw("Failed to get stdout from the job")
taskid = stack.raw_stdout_via_worker("user")
MiqTask.wait_for_taskid(taskid)
expect(MiqTask.find(taskid).message).to include("Failed to get stdout from the job")
expect(MiqTask.find(taskid).status).to eq("Error")
end
end
end

context "when embedded_terraform role is disabled" do
describe "#raw_stdout_via_worker return error" do
let(:role_enabled) { false }

it "returns an error message" do
taskid = stack.raw_stdout_via_worker("user")
expect(MiqTask.find(taskid)).to have_attributes(
:message => "Cannot get standard output of this terraform-template because the embedded terraform role is not enabled",
:status => "Error"
)
end
end
end
end
end

0 comments on commit 4c66529

Please sign in to comment.