Skip to content

Commit

Permalink
Update healthchecks to handle ldd failures
Browse files Browse the repository at this point in the history
Signed-off-by: adfoster-r7 <[email protected]>
  • Loading branch information
adfoster-r7 committed Nov 22, 2023
1 parent 56015cb commit 825b958
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 7 deletions.
38 changes: 31 additions & 7 deletions lib/omnibus/health_check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -511,16 +511,40 @@ def read_shared_libs(find_command, ldd_command, &output_proc)
# feed the list of files to the "ldd" command
#

# this command will typically fail if the last file isn't a valid lib/binary which happens often
ldd_output = shellout(ldd_command, input: find_output.join).stdout
# instance Mixlib::ShellOut
ldd_cmd = shellout(ldd_command, input: find_output.join)

# Optimized path: Attempt to run the `ldd` command on all file paths. If it succeeds, then process
# the stdout result in bulk. If the command returned a non-zero exit status code, then something went wrong.
# Each path will have to be manually resolved
unless ldd_cmd.error?
# do the output process to determine if the files are good or bad
ldd_cmd.stdout.each_line do |line|
output_proc.call(line)
end
else
log.debug(log_key) { "Failed running #{ldd_command} with exit status #{ldd_cmd.exitstatus} when resolving individually" }

#
# do the output process to determine if the files are good or bad
#
# Verify each path separately
find_output.each do |path|
ldd_cmd = shellout(ldd_command, input: path)
if ldd_cmd.error?
log.debug(log_key) { "Failed running #{ldd_command} with exit status #{ldd_cmd.exitstatus} against: #{path}" }
end

ldd_output.each_line do |line|
output_proc.call(line)
ldd_output = ldd_cmd.stdout

# Yield the path first
output_proc.call("#{path.rstrip}:")

# do the output process to determine if the files are good or bad
ldd_output.each_line do |line|
output_proc.call(line)
end
end
end

nil
end

#
Expand Down
54 changes: 54 additions & 0 deletions spec/unit/health_check_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,28 @@ def mkdump(base, size, x64 = false)
let(:file_list) do
double("Mixlib::Shellout",
error!: false,
error?: false,
stdout: <<~EOH
/opt/chefdk/shouldnt/matter
EOH
)
end

let(:file_list_multiple) do
double("Mixlib::Shellout",
error!: false,
error?: false,
stdout: <<~EOH
/opt/chefdk/first
/opt/chefdk/second
EOH
)
end

let(:empty_list) do
double("Mixlib::Shellout",
error!: false,
error?: false,
stdout: <<~EOH
EOH
)
Expand All @@ -130,6 +143,7 @@ def mkdump(base, size, x64 = false)
let(:bad_list) do
double("Mixlib::Shellout",
error!: false,
error?: false,
stdout: <<~EOH
/somewhere/other/than/install/dir
EOH
Expand All @@ -139,6 +153,7 @@ def mkdump(base, size, x64 = false)
let(:bad_healthcheck) do
double("Mixlib::Shellout",
error!: false,
error?: false,
stdout: <<~EOH
/bin/ls:
linux-vdso.so.1 => (0x00007fff583ff000)
Expand All @@ -161,6 +176,7 @@ def mkdump(base, size, x64 = false)
let(:good_healthcheck) do
double("Mixlib::Shellout",
error!: false,
error?: false,
stdout: <<~EOH
/bin/echo:
linux-vdso.so.1 => (0x00007fff8a6ee000)
Expand All @@ -174,6 +190,17 @@ def mkdump(base, size, x64 = false)
)
end

let(:bad_exitstatus_healthcheck) do
double("Mixlib::Shellout",
error!: -> { raise Mixlib::ShellOut::ShellCommandFailed },
error?: true,
exitstatus: 135,
stdout: <<~EOH
/bin/echo:
EOH
)
end

it "raises an exception when there are external dependencies" do
allow(subject).to receive(:shellout)
.with("find /opt/chefdk/ -type f | xargs file | grep \"ELF\" | awk -F: '{print $1}' | sed -e 's/:$//'")
Expand All @@ -198,6 +225,33 @@ def mkdump(base, size, x64 = false)
expect { subject.run! }.to_not raise_error
end

it "does checks lld for each file if the initial bulk ldd command fails" do
allow(subject).to receive(:shellout)
.with("find /opt/chefdk/ -type f | xargs file | grep \"ELF\" | awk -F: '{print $1}' | sed -e 's/:$//'")
.and_return(file_list_multiple)

# Bulk ldd command fails
allow(subject).to receive(:shellout)
.with("xargs ldd", { input: "/opt/chefdk/first\n/opt/chefdk/second\n" })
.and_return(bad_exitstatus_healthcheck)

# First file ldd fails
allow(subject).to receive(:shellout)
.with("xargs ldd", { input: "/opt/chefdk/first\n" })
.and_return(bad_exitstatus_healthcheck)

# Second file lld succeeds
allow(subject).to receive(:shellout)
.with("xargs ldd", { input: "/opt/chefdk/second\n" })
.and_return(good_healthcheck)

output = capture_logging do
expect { subject.run! }.to_not raise_error
end
expect(output).to match(/Failed running xargs ldd with exit status 135 when resolving individually/)
expect(output).to match(%r{Failed running xargs ldd with exit status 135 against: /opt/chefdk/first})
end

it "will not perform dll base relocation checks" do
expect(subject.relocation_checkable?).to be false
end
Expand Down

0 comments on commit 825b958

Please sign in to comment.