Skip to content

Commit feb28e3

Browse files
committed
Update healthchecks to handle ldd failures
Signed-off-by: adfoster-r7 <[email protected]>
1 parent 82dae89 commit feb28e3

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

lib/omnibus/health_check.rb

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -511,16 +511,40 @@ def read_shared_libs(find_command, ldd_command, &output_proc)
511511
# feed the list of files to the "ldd" command
512512
#
513513

514-
# this command will typically fail if the last file isn't a valid lib/binary which happens often
515-
ldd_output = shellout(ldd_command, input: find_output.join).stdout
514+
# instance Mixlib::ShellOut
515+
ldd_cmd = shellout(ldd_command, input: find_output.join)
516+
517+
# Optimized path: Attempt to run the `ldd` command on all file paths. If it succeeds, then process
518+
# the stdout result in bulk. If the command returned a non-zero exit status code, then something went wrong.
519+
# Each path will have to be manually resolved
520+
unless ldd_cmd.error?
521+
# do the output process to determine if the files are good or bad
522+
ldd_cmd.stdout.each_line do |line|
523+
output_proc.call(line)
524+
end
525+
else
526+
log.debug(log_key) { "Failed running #{ldd_command} with exit status #{ldd_cmd.exitstatus} when resolving individually" }
516527

517-
#
518-
# do the output process to determine if the files are good or bad
519-
#
528+
# Verify each path separately
529+
find_output.each do |path|
530+
ldd_cmd = shellout(ldd_command, input: path)
531+
if ldd_cmd.error?
532+
log.debug(log_key) { "Failed running #{ldd_command} with exit status #{ldd_cmd.exitstatus} against: #{path}" }
533+
end
520534

521-
ldd_output.each_line do |line|
522-
output_proc.call(line)
535+
ldd_output = ldd_cmd.stdout
536+
537+
# Yield the path first
538+
output_proc.call("#{path.rstrip}:")
539+
540+
# do the output process to determine if the files are good or bad
541+
ldd_output.each_line do |line|
542+
output_proc.call(line)
543+
end
544+
end
523545
end
546+
547+
nil
524548
end
525549

526550
#

spec/unit/health_check_spec.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,28 @@ def mkdump(base, size, x64 = false)
103103
let(:file_list) do
104104
double("Mixlib::Shellout",
105105
error!: false,
106+
error?: false,
106107
stdout: <<~EOH
107108
/opt/chefdk/shouldnt/matter
108109
EOH
109110
)
110111
end
111112

113+
let(:file_list_multiple) do
114+
double("Mixlib::Shellout",
115+
error!: false,
116+
error?: false,
117+
stdout: <<~EOH
118+
/opt/chefdk/first
119+
/opt/chefdk/second
120+
EOH
121+
)
122+
end
123+
112124
let(:empty_list) do
113125
double("Mixlib::Shellout",
114126
error!: false,
127+
error?: false,
115128
stdout: <<~EOH
116129
EOH
117130
)
@@ -130,6 +143,7 @@ def mkdump(base, size, x64 = false)
130143
let(:bad_list) do
131144
double("Mixlib::Shellout",
132145
error!: false,
146+
error?: false,
133147
stdout: <<~EOH
134148
/somewhere/other/than/install/dir
135149
EOH
@@ -139,6 +153,7 @@ def mkdump(base, size, x64 = false)
139153
let(:bad_healthcheck) do
140154
double("Mixlib::Shellout",
141155
error!: false,
156+
error?: false,
142157
stdout: <<~EOH
143158
/bin/ls:
144159
linux-vdso.so.1 => (0x00007fff583ff000)
@@ -161,6 +176,7 @@ def mkdump(base, size, x64 = false)
161176
let(:good_healthcheck) do
162177
double("Mixlib::Shellout",
163178
error!: false,
179+
error?: false,
164180
stdout: <<~EOH
165181
/bin/echo:
166182
linux-vdso.so.1 => (0x00007fff8a6ee000)
@@ -174,6 +190,17 @@ def mkdump(base, size, x64 = false)
174190
)
175191
end
176192

193+
let(:bad_exitstatus_healthcheck) do
194+
double("Mixlib::Shellout",
195+
error!: -> { raise Mixlib::ShellOut::ShellCommandFailed },
196+
error?: true,
197+
exitstatus: 135,
198+
stdout: <<~EOH
199+
/bin/echo:
200+
EOH
201+
)
202+
end
203+
177204
it "raises an exception when there are external dependencies" do
178205
allow(subject).to receive(:shellout)
179206
.with("find /opt/chefdk/ -type f | xargs file | grep \"ELF\" | awk -F: '{print $1}' | sed -e 's/:$//'")
@@ -198,6 +225,33 @@ def mkdump(base, size, x64 = false)
198225
expect { subject.run! }.to_not raise_error
199226
end
200227

228+
it "does checks lld for each file if the initial bulk ldd command fails" do
229+
allow(subject).to receive(:shellout)
230+
.with("find /opt/chefdk/ -type f | xargs file | grep \"ELF\" | awk -F: '{print $1}' | sed -e 's/:$//'")
231+
.and_return(file_list_multiple)
232+
233+
# Bulk ldd command fails
234+
allow(subject).to receive(:shellout)
235+
.with("xargs ldd", { input: "/opt/chefdk/first\n/opt/chefdk/second\n" })
236+
.and_return(bad_exitstatus_healthcheck)
237+
238+
# First file ldd fails
239+
allow(subject).to receive(:shellout)
240+
.with("xargs ldd", { input: "/opt/chefdk/first\n" })
241+
.and_return(bad_exitstatus_healthcheck)
242+
243+
# Second file lld succeeds
244+
allow(subject).to receive(:shellout)
245+
.with("xargs ldd", { input: "/opt/chefdk/second\n" })
246+
.and_return(good_healthcheck)
247+
248+
output = capture_logging do
249+
expect { subject.run! }.to_not raise_error
250+
end
251+
expect(output).to match(/Failed running xargs ldd with exit status 135 when resolving individually/)
252+
expect(output).to match(%r{Failed running xargs ldd with exit status 135 against: /opt/chefdk/first})
253+
end
254+
201255
it "will not perform dll base relocation checks" do
202256
expect(subject.relocation_checkable?).to be false
203257
end

0 commit comments

Comments
 (0)