29

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

garnertb
  • 9,454
  • 36
  • 38
Tampa
  • 75,446
  • 119
  • 278
  • 425

3 Answers3

45

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.

turtlebender
  • 1,907
  • 15
  • 16
  • 4
    If the template resource decides that it does not need to execute (i.e. if the file will not be changed) then the `notifies` don't happen. So with this approach it is possible, depending on your application, that your service will never be set up or started even with your application fully set up and ready to go. – wberry Nov 07 '13 at 04:03
  • so to get around that you would have another `service "nginx" do..` call below the template call that does an `action :start` right? Is that the preferred way of handling the possible issue you outlined or is there a more graceful way? – red888 Sep 02 '16 at 18:56
5
template "nginx" do
    path "/etc/init.d/nginx"
    source "nginx.erb"
    owner "root"
    group "root"
    mode "0755"
end

service "nginx" do
    supports :restart => true, :start => true, :stop => true, :reload => true
    action [ :enable, :start ]
    subscribes :restart, "template[nginx]", :immediately
end 
-2

While using notifies is better in this case, in other cases you don't have that luxury. Here's how to instruct Chef to create the template immediately:

tpl = template "nginx" do
  action :nothing
  path "/etc/init.d/nginx"
  source "nginx.erb"
  owner "root"
  group "root"
  mode "0755"
end
tpl.run_action(:create)
DV.
  • 4,585
  • 9
  • 37
  • 44
  • 2
    The reason this is not recommended is that invoking a resource's `run_action` method executes that resource before resources and even node attributes are fully *defined*. This could lead to truly bizarre issues. – wberry Nov 07 '13 at 03:59
  • This is highly discouraged. It will cause the template resource to be executed at compile time instead of converge time, so it will run before all other resources, including resources in cookbooks and recipes that come before this in the run list. Compile time execution is necessary for chef_gem to install before ruby 'requires' lines are evaluated and therefore necessary for build-essentials to install before chef_gems are run. Outside of those use cases where you are forced into it, compile time should never be used. – lamont Aug 11 '14 at 23:24