Chef, how to run a template that creates a init.d script before the service is created

Tampa picture Tampa · Mar 30, 2012 · Viewed 21.2k times · Source

Below is my templete for nginx.

I am facing a catch 22. I need to install a init.d template. So I have a nginx erb template that I place in /etc/init.d/nginx.

I Even tried t place the code on top of the recipe. The recipe is dependent on the init.d file but its not exectued until it is too late and as a result I get this error:

STDERR: update-rc.d: /etc/init.d/nginx: file does not exist
---- End output of "bash"  "/tmp/chef-script20120330-26326-3ologp-0" ----
Ran "bash"  "/tmp/chef-script20120330-26326-3ologp-0" returned 1
[Fri, 30 Mar 2012 06:22:15 +0000] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
[Fri, 30 Mar 2012 06:22:15 +0000] ERROR: Sleeping for 60 seconds before trying again

On the next run of chef client, things work because then the templete was created.

How do I execute a template immediately before I register the service resource for nginx? A quick fix is that I create a recipe that will run the template before nginx to install the template but that seems rather absurd.

This tempate needs to be installed before the service is registed.

template "nginx" do
      path "/etc/init.d/nginx"
      source "nginx.erb"
      owner "root"
      group "root"
      mode "0755"
    end

Then register the server.

service "nginx" do
      supports :restart => true, :start => true, :stop => true, :reload => true
      action [ :enable, :start]
    end







####################################
#Install Nginx
####################################
#http://wiki.nginx.org/HttpLuaModule#Installation
version = node[:nginx][:version]
package "libpcre3" do
  action :install
end
package "libpcre3-dev" do
  action :install
end
package "libpcre++-dev" do
  action :install
end
package "openssl" do
  action :install
end

template "nginx" do
  path "/etc/init.d/nginx"
  source "nginx.erb"
  owner "root"
  group "root"
  mode "0755"
end

#mkdir /var/log/nginx
directory "/var/log/nginx" do
  owner "root"
  group "root"
  mode "0755"
  action :create
  #not_if "test -f /etc/nginx/lock"
end

remote_file "/tmp/nginx-#{version}.tar.gz" do
  source "http://nginx.org/download/nginx-#{version}.tar.gz"
  checksum node[:nginx][:checksum]
  action :create_if_missing
  notifies :run, "bash[install_nginx]", :immediately
end


bash "install_nginx" do
  user "root"
  cwd "/tmp"
  code <<-EOH
    tar -xvf nginx-#{version}.tar.gz
    cd nginx-#{version}
    ./configure --with-http_stub_status_module  
    make -j2
    make install
    ln -s /usr/local/nginx/conf/ /etc/nginx
    /usr/sbin/update-rc.d -f nginx defaults
  EOH
  action :nothing
  creates "/usr/sbin/nginx"
  notifies :restart, "service[nginx]"
  #not_if "test -f /etc/redis/lock"
end


service "nginx" do
  supports :restart => true, :start => true, :stop => true, :reload => true
  action [ :enable, :start]
end

#ln -s /usr/local/nginx/conf/ /etc/nginx
#link "/usr/local/nginx/conf/" do
#  to "/etc/nginx"
#  link_type :hard
#end

link "/usr/local/nginx/logs/access.log" do
  to "/var/log/nginx/access.log"
end

link "/usr/local/nginx/logs/error.log" do
  to "/var/log/nginx/error.log"
end

file "/etc/nginx/lock" do
  owner "root"
  group "root"
  mode "0755"
  action :create_if_missing
end

template "nginx.conf" do
  path "/etc/nginx/nginx.conf"
  source "nginx.conf.erb"
  owner "root"
  group "root"
  mode "0644"
  #notifies :reload, "service[nginx]"
  notifies :reload, resources(:service => "nginx"), :immediately
end

Thanks

Answer

turtlebender picture turtlebender · Mar 30, 2012

You can set the action on the service to :nothing. Then have the template notify the service to enable. That way the template will be processed and then the service will be enabled:

service "nginx" do
  supports :restart => true, :start => true, :stop => true, :reload => true
  action :nothing
end 

template "nginx" do
  path "/etc/init.d/nginx"
  source "nginx.erb"
  owner "root"
  group "root"
  mode "0755"
  notifies :enable, "service[nginx]"
  notifies :start, "service[nginx]"
end

Then the service will wait until the template has processed.