chef - making yum localinstall of cookbook_file - ruby

I have some certain rpm's that need to be moved to a box, and yum localinstall'ed there.
Now I know how to make notifies for upon file creation yum would install something from repo, but I don't know how to specify source in this case.
So for now, I have the following:
cookbook_file "mksh-39-5.el6.x86_64.rpm" do
path "/tmp/mksh-39-5.el6.x86_64.rpm"
action :create
end
package "mksh-39-5.el6.x86_64.rpm" do
source "/tmp/mksh-39-5.el6.x86_64.rpm"
action :install
end
The question is - how do I bind them, so that installation would be called upon file creation?

The brief answer is "use notifications" but as you talk about many files I would loop over a list like this:
['mksh-39-5.el6.x86_64.rpm','package2.rpm'].each do |p| # start from an array of packages, could be an attributes like node['my_namespace']['packages']
package p do # no need to do interpolation here, we just need the name
source "/tmp/#{p}" # Here we have to concatenate path and name
action :nothing # do nothing, just define the resource
end
cookbook_file "/tmp/#{p}" do # I prefer setting the destination in the name
source p # and tell the source name, so in case of different platfom I can take advantage of the resolution of files withint the cookbook tree
action :create
notifies :install, "package[/tmp/#{p}]", :immediately
end
end
The :immediately is to fire the package install as soon as the file has been placed, if there's dependencies, you'll have to manage the order of the packages in the array

Related

Chef template resource to execute if the source template changes?

I'm deploying a package that requires a template be created in a specified directory every time a directory is unzipped.
A remote_file notifies my unzip action, that unzip action notifies the template resource, which in turn notifies other resources. This chain of notifications works as expected.
Below is my template resource:
template 'C:\\Program Files\\MyProgram\\program.yml' do
source "my_program-#{node['program']['version']}.yml.erb"
action :nothing
notifies :run, 'powershell_script[install-program]', :immediately
end
My question: Is there a way to have the template resource execute if I make a change to the source template? Right now it only executes the template resource if notified by my unzip action (due to my action :nothing).
However, it would be great to have a way for it to tell if the template itself has changed. Perhaps some kind of not_if or only_if statement?
sounds to me that you avoid all the notification chaining if you will have your resources defined in the same recipe.
back to your questions, it sounds that setting action :create, which is the default action, will do the trick. from the template resource documentation
action :create
Create a file. If a file already exists (but does not match), update that file to match.

Chef - Block not being executed even tho its notified?

i've looked over this code a few times and i'm not sure why the extract_presta block isnt being triggered. I've confirmed the file i'm looking for isnt in the /var/www/html directory :c)
What i'm trying to achieve is to:
download a file, unzip it, but only if a specific file doesn't exist
Stop apache after downloading, unzip the file
start apache
Could i ask for some advice please? thanks.
-nat
service "apache" do
action :nothing
end
execute 'extract_presta' do
command 'unzip /tmp/prestashop_1.7.4.2.zip'
cwd '/var/www/html'
not_if { File.exists?("/var/www/html/autoload.php") }
action :nothing
notifies :start, "service[apache]"
end
# Fetch the file. Maybe the file won't be fetched because of not_if or checksum.
# In that case apache won't be stopped or started, it will just keep running.
remote_file "/tmp/prestashop_1.7.4.2.zip" do
source "https://download.prestashop.com/download/releases/prestashop_1.7.4.2.zip"
notifies :stop, "service[apache]", :immediately
notifies :run, 'execute[extract_presta]', :immediately
end
Does the download already exist? If so, then the remote_file resource would be marked up-to-date and wouldn't fire notifications.

Is there a better way to delete an installer after installation, in chef

eg.
remote_file '/app/abc/' + '/app.rpm' do
source "https://location.com/app.rpm"
end
package 'app.rpm' do
source '/app/abc/app.rpm'
end
file '/app/abc/app.rpm' do
action :delete
end
This is how I am currently deleting the rpm file. Is there a better way to write the code, without having to include the file resource again ?
We generally recommend not deleting so you can use the file for idempotence checks, using a notification to run the package install if the remote file changes.

Why chef does not execute recipe line by line?

Problem is that chef tries to install template first, and only then installs packages. If i comment template block, chef will install sphinxsearch package fine.
But if template block is not commented, sphinxsearch package is not installed, and chef fails with error
resource template[/etc/sphinxsearch/sphinx.conf] is configured to notify resource service[sphinxsearch] with action reload, but service[sphinxsearch] cannot be found in the resource collection`
Why this happens?
##
# Install system packages
##
node['website']['packages'].each do |pkg|
log 'Installing ' + pkg
package pkg
end
##
# Configure sphinx
##
template "/etc/sphinxsearch/sphinx.conf" do
source 'sphinx.erb'
owner 'root'
group 'root'
mode 00644
notifies :reload, 'service[sphinxsearch]', :delayed
end
notifies and subscribes in chef are both trying to reach out to resources that have been defined in your chef run. They will then call teh indicated action on those resources. In your case:
notifies :reload, 'service[sphinxsearch]', :delayed
is looking for a resource of type service named sphinxsearch and call the reload action on it. If, at the end of the resource gathering (compile) phase, chef cannot find a service[sphinxsearch] resource, then it throws the error. You don't see the package installed because chef never enters the execution phase. (See this answer for more on the two phase nature of chef)
As indicated by #IsabelHM, you could solve the problem by adding
service 'sphinxsearch' do
action [:enable, :start]
end
I suggest you use [:enable, :start] rather than :nothing as this will ensure that the service is always running, even if your template doesn't change. Also, please note that the service resource does not add a service config for you. So if the sphinxsearch package does not add a service config, you'll also need a cookbook_file, template, or remote_file resource to create the service config with.
Add this in your recipe.
service 'sphinxsearch' do
action :nothing
end

Chef - Read a file from git repo at runtime and use parse value in recipe

I would like to read a file from a checkout git repository to parse a config file and use this data to perform few resources commands.
git "/var/repository" do
action :sync
end
config = JSON.parse(File.read("/var/repository/config.json" ))
config.each do |job, flags|
#do some resources stuff here
end
This will not work because the file doesn't exist at compile time:
================================================================================
Recipe Compile Error in /var/chef/cache/cookbooks/...
================================================================================
Errno::ENOENT
No such file or directory - /var/repository/config.json
I where trying to load the file in ruby_block and perform the Chef resource actions there, but this didn't worked. Also setting the parsed config to a variable and use it outside of the ruby_block didn't work.
ruby_block "load config" do
block do
config = JSON.parse(File.read("/var/repository/config.json"))
#node["config"] = config doesn't work - node["config"] will not be set
config.each do |job, flags|
#do some stuff - will not work because Chef context is missing
end
end
end
Any idea how I could read the file at runtime and used the parsed values in my recipe?
You may also find it helpful to use lazy evaluation in scenarios like this.
In some cases, the value for an attribute cannot be known until the execution phase of a chef-client run. In this situation, using lazy evaluation of attribute values can be helpful. Instead of an attribute being assigned a value, it may instead be assigned a code block.

Resources