I am trying to find the existence of Docker on a node with a guard before i install it.
the resource block looks like this:
ruby_block "install_docker" do
not_if {shell_out('docker -v').stdout =~ /Docker version/i}
block do
#command_out = shell_out('docker version --format '{{.Server.Version}}'')
end
action :create
notifies :write, 'log[installing_docker_log]', :immediately
notifies :install, 'package[install_docker_ce]', :immediately
notifies :install, 'yum_package[install_docker_ce_cli]', :immediately
notifies :install, 'yum_package[install_containerd_io]', :immediately
notifies :create, "directory[create_docker_dir]", :immediately
notifies :create, "directory[create_etc_docker_dir]", :immediately
notifies :create, "cookbook_file[create_docker_daemon_json]", :immediately
notifies :create, "cookbook_file[create_docker_99_docker_config]", :immediately
notifies :run, "execute[chgrp docker_dir]", :immediately
notifies :run, "execute[chmod docker_dir]", :immediately
notifies :run, "execute[chgrp /etc/docker]", :immediately
notifies :run, "execute[chmod /etc/docker]", :immediately end
when running in kitchen i get this output saying the guard fails. It fails in the case when docker is not installed. So i assume the shell_out function is throwing an exception, but i am new to ruby and chef so am not sure how to silence it.
Do i want to check if docker is installed another way? Any help y’all could provide is greatly appreciated.
Compiled Resource:
------------------
# Declared in /tmp/kitchen/cache/cookbooks/kpmi_linux_base/recipes/install_docker.rb:54:in `from_file'
ruby_block("install_docker") do
action [:create]
default_guard_interpreter :default
declared_type :ruby_block
cookbook_name "kpmi_linux_base"
recipe_name "install_docker"
block #<Proc:0x000000000470c8b8 /tmp/kitchen/cache/cookbooks/kpmi_linux_base/recipes/install_docker.rb:56>
not_if { #code block }
end
System Info:
------------
chef_version=16.1.16
platform=centos
platform_version=7.6.1810
ruby=ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
program_name=/opt/chef/bin/chef-client
executable=/opt/chef/bin/chef-client
Running handlers:
[2020-06-05T18:30:39+00:00] ERROR: Running exception handlers
Running handlers complete
[2020-06-05T18:30:39+00:00] ERROR: Exception handlers complete
Chef Infra Client failed. 0 resources updated in 10 seconds
[2020-06-05T18:30:39+00:00] FATAL: Stacktrace dumped to /tmp/kitchen/cache/chef-stacktrace.out
[2020-06-05T18:30:39+00:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2020-06-05T18:30:39+00:00] FATAL: Errno::ENOENT: ruby_block[install_docker] (kpmi_linux_base::install_docker line 54) had an error: Errno::ENOENT: No such file or directory - docker
2
Answers
you can test whether docker engine is installed in many ways, here are some.
and you can find many other ways to check whether docker exist…
Your problem is not “How to tell, if docker is installed”, but actually in how you use Chef. You are trying to write an ordinary bash script using Chef resources. This does not give you any advantage over bash script, but even more complicates the matter.
Looking at your code I see that you:
Chef is smart, so you don’t have to do point 1. Go to the point 2 straight away. Your recipe should look something like that:
Most Chef built-in resources (like package, directory, file etc.), except execute, ruby_block and other resources that just run arbitrary code, are idempotent. That means if the package is already installed, it will not try to install it again, if the directory exists, it will not try to create it etc. So you don’t have to make checks yourself, Chef will do that. You only need to describe the desired state of your machine.
Also pay attention, that you don’t need your
execute
resources that change mode or group, you can set the mode and owner/group right inside thedirectory
orcookbook_file
resource itself.