Render partial template only if the node-partial exists

Hiya,

How can I render a base template plus a partial template only if the partial
exists for node[‘fqdn’]? Is there a way to do this? The way I see it now, the
only way I can do this is to create a per-fqdn erb files in my cookbook for
every host, even if only a few of them actually need to render the partial. I’ll
bet there’s a better way to do this, I just don’t see it yet.

Let’s say I have a bunch of mysql database hosts, and most of them can render
their my.cnf following one standard. And let’s say sometimes I have a need to
extend the standard by appending extra config lines for only some of the db
hosts.

Here are examples of the rendered my.cnf I want, the first is for a db host that
has no special config lines, the second for a db host that needs a lil extra:

[mysqld]
server-id = 14050101
report-host = db14b.dev.example.com
!include /etc/mysql/_my.cnf_m3.large
!include /etc/mysql/_my.cnf.global_5.5

[mysqld]
server-id = 14050701
report-host = db26b.dev.example.com
!include /etc/mysql/_my.cnf_m3.large
!include /etc/mysql/_my.cnf.global_5.5

special stuff for this host is below, brought to you by chef partial template:

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

The template resource in the recipe:

template “/etc/mysql/my.cnf” do
source "my.cnf.erb"
owner "root"
group "root"
mode 00644
variables :server_id => node[‘tokopf-bar’][‘mysql’][‘server_id’],
:mysql_version => node[‘tokopf-bar’][‘mysql’][‘mysql_version’]
end

The main template, my.cnf.erb:
[mysqld]
server-id = <%= @server_id %>
report-host = <%= node[‘fqdn’] %>
!include /etc/mysql/my.cnf<%= node[‘ec2’][‘instance_type’] %>
!include /etc/mysql/my.cnf.global<%= @mysql_version %>
<%= render @node[‘fqdn’] + “.mycnf-partial.erb” -%>

cookbooks/tokopf-bar/templates/default/db14b.dev.example.com.mycnf-partial.erb is empty…

cookbooks/tokopf-bar/templates/default/db26b.dev.example.com.mycnf-partial.erb:

special stuff for this host is below, brought to you by chef partial template:

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

Thanks!
kallen

I don't think this is currently possible without a lot of extra work. The complex way would be to look at the cookbook metadata in the cookbook collection to see what template files exist. This is definitely not how templates are intended to be used at present though.

--Noah

On May 12, 2014, at 12:13 PM, kallen@groknaut.net wrote:

Hiya,

How can I render a base template plus a partial template only if the partial
exists for node['fqdn']? Is there a way to do this? The way I see it now, the
only way I can do this is to create a per-fqdn erb files in my cookbook for
every host, even if only a few of them actually need to render the partial. I'll
bet there's a better way to do this, I just don't see it yet.

Let's say I have a bunch of mysql database hosts, and most of them can render
their my.cnf following one standard. And let's say sometimes I have a need to
extend the standard by appending extra config lines for only some of the db
hosts.

Here are examples of the rendered my.cnf I want, the first is for a db host that
has no special config lines, the second for a db host that needs a lil extra:

[mysqld]
server-id = 14050101
report-host = db14b.dev.example.com
!include /etc/mysql/_my.cnf_m3.large
!include /etc/mysql/_my.cnf.global_5.5

[mysqld]
server-id = 14050701
report-host = db26b.dev.example.com
!include /etc/mysql/_my.cnf_m3.large
!include /etc/mysql/_my.cnf.global_5.5

special stuff for this host is below, brought to you by chef partial template:

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

The template resource in the recipe:

template "/etc/mysql/my.cnf" do
source "my.cnf.erb"
owner "root"
group "root"
mode 00644
variables :server_id => node['tokopf-bar']['mysql']['server_id'],
:mysql_version => node['tokopf-bar']['mysql']['mysql_version']
end

The main template, my.cnf.erb:
[mysqld]
server-id = <%= @server_id %>
report-host = <%= node['fqdn'] %>
!include /etc/mysql/my.cnf<%= node['ec2']['instance_type'] %>
!include /etc/mysql/my.cnf.global<%= @mysql_version %>
<%= render @node['fqdn'] + ".mycnf-partial.erb" -%>

cookbooks/tokopf-bar/templates/default/db14b.dev.example.com.mycnf-partial.erb is empty...

cookbooks/tokopf-bar/templates/default/db26b.dev.example.com.mycnf-partial.erb:

special stuff for this host is below, brought to you by chef partial template:

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

Thanks!
kallen

OK.. I found a solution:

The main template, my.cnf.erb:
[mysqld]
server-id = <%= @server_id %>
report-host = <%= node['fqdn'] %>
!include /etc/mysql/my.cnf<%= node['ec2']['instance_type'] %>
!include /etc/mysql/my.cnf.global<%= @mysql_version %>
!include /etc/mysql/_my.cnf.instance_specific_overrides <-- the new line

In the templates dir in the cookbook:
$ cat templates/default/my.cnf.instance_specific_overrides.erb

A placeholder for overrides for specific fqdn

$ cat templates/host-db26.dev.example.com/my.cnf.instance_specific_overrides.erb

Overrides specific to <%= node['fqdn'] %>

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

Two template resources in the recipe:

template "/etc/mysql/my.cnf" do
source "my.cnf.erb"
owner "root"
group "root"
mode 00644
variables :server_id => node['tokopf-bar']['mysql']['server_id'],
:mysql_version => node['tokopf-bar']['mysql']['mysql_version']
end

template "#{node['tokopf-bar']['mysql']['conf_dir']}/_my.cnf.instance_specific_overrides" do
source "my.cnf.instance_specific_overrides.erb"
owner "root"
group node['tokopf-bar']['mysql']['root_group']
mode 00644
end

On a given node during a chef-client run, if this dir exists with this file in
it, chef will lay down this file:

templates/host-FQDN/my.cnf.instance_specific_overrides.erb

Otherwise, chef will lay down the override file found in the default dir.

Either way, the resulting my.cnf is happy.

yay
kallen

On Mon, 12 May 2014, Noah Kantrowitz wrote:

I don't think this is currently possible without a lot of extra work. The complex way would be to look at the cookbook metadata in the cookbook collection to see what template files exist. This is definitely not how templates are intended to be used at present though.

--Noah

On May 12, 2014, at 12:13 PM, kallen@groknaut.net wrote:

Hiya,

How can I render a base template plus a partial template only if the partial
exists for node['fqdn']? Is there a way to do this? The way I see it now, the
only way I can do this is to create a per-fqdn erb files in my cookbook for
every host, even if only a few of them actually need to render the partial. I'll
bet there's a better way to do this, I just don't see it yet.

Let's say I have a bunch of mysql database hosts, and most of them can render
their my.cnf following one standard. And let's say sometimes I have a need to
extend the standard by appending extra config lines for only some of the db
hosts.

Here are examples of the rendered my.cnf I want, the first is for a db host that
has no special config lines, the second for a db host that needs a lil extra:

[mysqld]
server-id = 14050101
report-host = db14b.dev.example.com
!include /etc/mysql/_my.cnf_m3.large
!include /etc/mysql/_my.cnf.global_5.5

[mysqld]
server-id = 14050701
report-host = db26b.dev.example.com
!include /etc/mysql/_my.cnf_m3.large
!include /etc/mysql/_my.cnf.global_5.5

special stuff for this host is below, brought to you by chef partial template:

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

The template resource in the recipe:

template "/etc/mysql/my.cnf" do
source "my.cnf.erb"
owner "root"
group "root"
mode 00644
variables :server_id => node['tokopf-bar']['mysql']['server_id'],
:mysql_version => node['tokopf-bar']['mysql']['mysql_version']
end

The main template, my.cnf.erb:
[mysqld]
server-id = <%= @server_id %>
report-host = <%= node['fqdn'] %>
!include /etc/mysql/my.cnf<%= node['ec2']['instance_type'] %>
!include /etc/mysql/my.cnf.global<%= @mysql_version %>
<%= render @node['fqdn'] + ".mycnf-partial.erb" -%>

cookbooks/tokopf-bar/templates/default/db14b.dev.example.com.mycnf-partial.erb is empty...

cookbooks/tokopf-bar/templates/default/db26b.dev.example.com.mycnf-partial.erb:

special stuff for this host is below, brought to you by chef partial template:

[mysqld]
expire_logs_days=5
replicate-wild-ignore-table = foo_bar.KBToyAndHobby%

Thanks!
kallen