# How to override node attribute with lazy value?

**URL:** <https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889>\
**Category:** Chef Infra (archive)\
**Created:** [October 2, 2014, 10:13am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889 "2014-10-02T10:13:31Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![fletchowns](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/fletchowns/32/53_2.png) [@fletchowns](https://discourse.chef.io/u/fletchowns)\
**Post date:** [October 2, 2014, 10:13am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/1 "2014-10-02T10:13:31Z")

</div>

The chef-server readme  
[https://github.com/opscode-cookbooks/chef-server/blob/master/attributes/default.rb](https://github.com/opscode-cookbooks/chef-server/blob/master/attributes/default.rb)  
shows how to override nginx attributes. However, it doesn’t seem to work  
like I want it to when I do:

node.override[“chef-server”][“configuration”][“nginx”][“ssl\_certificate”] =  
"/etc/pki/tls/certs/#{node[:fqdn]}.pem"

node[:fqdn] is being updated during my chef run using the hostname cookbook  
[https://github.com/3ofcoins/chef-cookbook-hostname](https://github.com/3ofcoins/chef-cookbook-hostname), and so using the  
above results in an error because chef-server ends up looking for  
/etc/pki/tls/certs/localhost.pem (the old hostname), when it should instead  
be using /etc/pki/tls/certs/mynode.mycompany.com.pem.

So I think I want something like the following, but this doesn’t work.  
What’s the right way to do it?

node.override[“chef-server”][“configuration”][“nginx”][“ssl\_certificate”] =  
lazy { “/etc/pki/tls/certs/#{node[:fqdn]}.pem” }

Thanks,  
Greg

---

<div class="post-metadata">

**Author:** ![coderanger](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/coderanger/32/5_2.png) [@coderanger](https://discourse.chef.io/u/coderanger)\
**Post date:** [October 2, 2014, 2:55pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/2 "2014-10-02T14:55:54Z")

</div>

On Oct 2, 2014, at 3:13 AM, Greg Barker [fletch@fletchowns.net](mailto:fletch@fletchowns.net) wrote:

> The chef-server readme shows how to override nginx attributes. However, it doesn't seem to work like I want it to when I do:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] = "/etc/pki/tls/certs/#{node[:fqdn]}.pem"
> 
> node[:fqdn] is being updated during my chef run using the hostname cookbook, and so using the above results in an error because chef-server ends up looking for /etc/pki/tls/certs/localhost.pem (the old hostname), when it should instead be using /etc/pki/tls/certs/mynode.mycompany.com.pem.
> 
> So I think I want something like the following, but this doesn't work. What's the right way to do it?
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] = lazy { "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }

lazy{} is a feature of resources, not of node attributes. See [Derived Attributes in Chef – Noah Kantrowitz](https://coderanger.net/derived-attributes/) for more information about how to handle delayed interpolation in node attributes.

--Noah

---

<div class="post-metadata">

**Author:** ![fletchowns](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/fletchowns/32/53_2.png) [@fletchowns](https://discourse.chef.io/u/fletchowns)\
**Post date:** [October 10, 2014, 3:13am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/3 "2014-10-10T03:13:21Z")

</div>

Thanks Lamont. I tried using the system  
[https://github.com/xhost-cookbooks/system](https://github.com/xhost-cookbooks/system) cookbook which seems to do as  
you have suggested (setting the automatic\_attrs  
[https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48](https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48))  
but it still doesn't work.

The system cookbook is first in my run list and then towards the end it  
gets to my recipe which contains:  
node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
"/etc/pki/tls/certs/#{node['fqdn']}.pem"  
...but it still thinks node['fqdn'] is localhost, it doesn't get the  
updated value.

I guess I will just have to steer clear of relying on node['fqdn'] unless  
you have any other ideas, it's a bummer that so many cookbooks use it  
though.

Greg

On Sat, Oct 4, 2014 at 10:27 AM, Lamont Granquist [lamont@opscode.com](mailto:lamont@opscode.com)  
wrote:

> On 10/3/14, 5:13 PM, Lamont Granquist wrote:
> 
> > On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> > 
> > > How it should be written, i'll look at submitting a PR...
> > 
> > Sorry look like I fell victim to thinking that all problems were like my  
> > last problem.
> > 
> > The hostname is getting set at converge time, fairly late, by the  
> > hostname cookbook. Your node['fqdn'] will be the old hostname throughout  
> > the whole compile phase of the chef-client run. In your case since you  
> > control the code it'll be way easier to use the node['set\_fqdn'] attribute  
> > that you're passing to the hostname cookbook to pass to the  
> > chef-server cookbook:
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > = "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"
> > 
> > If that doesn't work for you then you may have an issue trying to do  
> > that. The attributes are most likely getting passed into the template  
> > variable sometime in compiletime and your node['fqdn'] isn't getting  
> > updated until converge time. Either the hostname cookbook needs to be  
> > changed to do its work at compile-time or else the chef-server cookbook  
> > needs to be converted to be lazy.
> > 
> > A better approach would probably be for the hostname cookbook to expose a  
> > ruby library to call to get the desired hostname (basically sugar around  
> > either returning node['set\_fqdn'] or else returning the output of  
> > "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'") and then you  
> > could get that value at compile time and set attributes with it just fine.
> > 
> > So, I'd actually suggest doing something more like this than using that  
> > hostname cookbook:
> 
> self.class.send(:include, Chef::Mixin::ShellOut)
> 
> # execute very early
> 
> execute "set hostname to nodename" do  
> command "/bin/hostname #{node.name}"  
> action :nothing  
> not\_if "shell\_out!('hostname').stdout.chomp == node.name"  
> end.run\_action(:run)
> 
> # fake out ohai data
> 
> node.automatic\_attrs["hostname"] = node.name[/[^.]_/]  
> node.automatic\_attrs["domain"] = node.name[/.(._)/, 1]  
> node.automatic\_attrs["machinename"] = node.name  
> node.automatic\_attrs["fqdn"] = node.name
> 
> case node["platform\_family"]  
> when "rhel", "fedora"  
> template "/etc/sysconfig/network" do  
> source "redhat-network.erb"  
> end  
> when "debian"  
> template "/etc/hostname" do  
> source "ubuntu-hostname.erb"  
> end  
> end
> 
> That encodes my policy that node names are fqdns and that the fqdn is set  
> from the node name and that hostnames are fqdns. If you have a different  
> policy, you can modify that code. The important bit is that I set the  
> hostname of the box at compile time at the top of my run\_list. Then I  
> override the ohai automatic attrs at compile time so that all later code  
> will see that. The templates can wait until converge time since those are  
> only going to be necessary on next boot.
> 
> You can quibble with this because clearly there's a problem with  
> separation of concerns and we "should" be calling ohai to reload the node  
> data, but if you do that, you need to make sure that you're doing that at  
> compile time. You could wrap the hostname cookbook's recipe logic in an  
> LWRP and then simply force that to run at compile time. I don't care about  
> that because I know what the ohai policy on those attrs are and that we're  
> unlikely to change it so I'm not too concerned about duplicating the code  
> and forcing it like that.
> 
> And the function of setting the current hostname and fixing the ohai data  
> is separate from the function of updating the templates. If I was doing  
> this reusably I'd keep those separate. I'd also keep 'finding the  
> hostname' separate and probably just put that in a straight up ruby library  
> function. That would be function or set of functions that you could use to  
> poke vmware or xenserver or whatever to see what your hostname is set as in  
> the hypervisor and use that.

---

<div class="post-metadata">

**Author:** ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)\
**Post date:** [October 10, 2014, 3:39am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/4 "2014-10-10T03:39:06Z")

</div>

"setting the automatic\_attrs" wasn't really the point of that code I  
pasted there. the point is to execute it at compile time rather than  
converge time. the code you point to in the system cookbook is inside  
of a provider and will also get executed at converge time. you can call  
the system\_hostname LWRP yourself and force it to run at compile time by  
method chaining .run\_action(:set) off of it (and add an `action :nothing` attribute inside the LWRP).

On 10/9/14, 8:13 PM, Greg Barker wrote:

> Thanks Lamont. I tried using the system  
> [https://github.com/xhost-cookbooks/system](https://github.com/xhost-cookbooks/system) cookbook which seems to do  
> as you have suggested (setting the automatic\_attrs  
> [https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48](https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48))  
> but it still doesn't work.
> 
> The system cookbook is first in my run list and then towards the end  
> it gets to my recipe which contains:  
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> = "/etc/pki/tls/certs/#{node['fqdn']}.pem"  
> ...but it still thinks node['fqdn'] is localhost, it doesn't get the  
> updated value.
> 
> I guess I will just have to steer clear of relying on node['fqdn']  
> unless you have any other ideas, it's a bummer that so many cookbooks  
> use it though.
> 
> Greg
> 
> On Sat, Oct 4, 2014 at 10:27 AM, Lamont Granquist \<[lamont@opscode.com](mailto:lamont@opscode.com)  
> [mailto:lamont@opscode.com](mailto:lamont@opscode.com)\> wrote:
> 
> ```
> On 10/3/14, 5:13 PM, Lamont Granquist wrote:
> 
> On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> 
> How it should be written, i'll look at submitting a PR...
> 
> Sorry look like I fell victim to thinking that all problems
> were like my last problem.
> 
> The hostname is getting set at converge time, fairly late, by
> the hostname cookbook. Your node['fqdn'] will be the old
> hostname throughout the whole compile phase of the chef-client
> run. In your case since you control the code it'll be way
> easier to use the node['set_fqdn'] attribute that you're
> passing to the hostname cookbook to pass to the
> chef-server cookbook:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl_certificate"]
> = "/etc/pki/tls/certs/#{node['set_fqdn']}.pem"
> 
> If that doesn't work for you then you may have an issue trying
> to do that. The attributes are most likely getting passed
> into the template variable sometime in compiletime and your
> node['fqdn'] isn't getting updated until converge time. 
> Either the hostname cookbook needs to be changed to do its
> work at compile-time or else the chef-server cookbook needs to
> be converted to be lazy.
> 
> A better approach would probably be for the hostname cookbook
> to expose a ruby library to call to get the desired hostname
> (basically sugar around either returning node['set_fqdn'] or
> else returning the output of "/usr/sbin/vmtoolsd --cmd
> 'info-get guestinfo.hostname'") and then you could get that
> value at compile time and set attributes with it just fine.
> 
> So, I'd actually suggest doing something more like this than using
> that hostname cookbook:
> 
> self.class.send(:include, Chef::Mixin::ShellOut)
> 
> # execute very early
> execute "set hostname to nodename" do
> command "/bin/hostname #{node.name <http://node.name>}"
> action :nothing
> not_if "shell_out!('hostname').stdout.chomp == node.name
> <http://node.name>"
> end.run_action(:run)
> 
> # fake out ohai data
> node.automatic_attrs["hostname"] = node.name
> <http://node.name>[/[^\.]*/]
> node.automatic_attrs["domain"] = node.name
> <http://node.name>[/\.(.*)/, 1]
> node.automatic_attrs["machinename"] = node.name <http://node.name>
> node.automatic_attrs["fqdn"] = node.name <http://node.name>
> 
> case node["platform_family"]
> when "rhel", "fedora"
> template "/etc/sysconfig/network" do
> source "redhat-network.erb"
> end
> when "debian"
> template "/etc/hostname" do
> source "ubuntu-hostname.erb"
> end
> end
> 
> That encodes my policy that node names are fqdns and that the fqdn
> is set from the node name and that hostnames are fqdns. If you
> have a different policy, you can modify that code. The important
> bit is that I set the hostname of the box at compile time at the
> top of my run_list. Then I override the ohai automatic attrs at
> compile time so that all later code will see that. The templates
> can wait until converge time since those are only going to be
> necessary on next boot.
> 
> You can quibble with this because clearly there's a problem with
> separation of concerns and we "should" be calling ohai to reload
> the node data, but if you do that, you need to make sure that
> you're doing that at compile time. You could wrap the hostname
> cookbook's recipe logic in an LWRP and then simply force that to
> run at compile time. I don't care about that because I know what
> the ohai policy on those attrs are and that we're unlikely to
> change it so I'm not too concerned about duplicating the code and
> forcing it like that.
> 
> And the function of setting the current hostname and fixing the
> ohai data is separate from the function of updating the
> templates. If I was doing this reusably I'd keep those separate. 
> I'd also keep 'finding the hostname' separate and probably just
> put that in a straight up ruby library function. That would be
> function or set of functions that you could use to poke vmware or
> xenserver or whatever to see what your hostname is set as in the
> hypervisor and use that.
> 
> ```

---

<div class="post-metadata">

**Author:** ![Mathieu\_Martin](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/mathieu_martin/32/60_2.png) [@Mathieu\_Martin](https://discourse.chef.io/u/Mathieu_Martin)\
**Post date:** [October 11, 2014, 6:33pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/5 "2014-10-11T18:33:53Z")

</div>

A lot of people also just sidestep all of this fun by setting the hostname  
at bootstrap time, before the initial Chef run.

Although the problem comes back in full, if you need to change the hostname  
later 🙂

Mat

On Thursday, October 9, 2014, Lamont Granquist [lamont@opscode.com](mailto:lamont@opscode.com) wrote:

> "setting the automatic\_attrs" wasn't really the point of that code I  
> pasted there. the point is to execute it at compile time rather than  
> converge time. the code you point to in the system cookbook is inside of a  
> provider and will also get executed at converge time. you can call the  
> system\_hostname LWRP yourself and force it to run at compile time by method  
> chaining .run\_action(:set) off of it (and add an `action :nothing`  
> attribute inside the LWRP).
> 
> On 10/9/14, 8:13 PM, Greg Barker wrote:
> 
> Thanks Lamont. I tried using the system  
> [https://github.com/xhost-cookbooks/system](https://github.com/xhost-cookbooks/system) cookbook which seems to do as  
> you have suggested (setting the automatic\_attrs  
> [https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48](https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48))  
> but it still doesn't work.
> 
> The system cookbook is first in my run list and then towards the end it  
> gets to my recipe which contains:  
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> = "/etc/pki/tls/certs/#{node['fqdn']}.pem"  
> ...but it still thinks node['fqdn'] is localhost, it doesn't get the  
> updated value.
> 
> I guess I will just have to steer clear of relying on node['fqdn'] unless  
> you have any other ideas, it's a bummer that so many cookbooks use it  
> though.
> 
> Greg
> 
> On Sat, Oct 4, 2014 at 10:27 AM, Lamont Granquist \<[lamont@opscode.com](mailto:lamont@opscode.com)  
> \<javascript:\_e(%7B%7D,'cvml','lamont@opscode.com');\>\> wrote:
> 
> > On 10/3/14, 5:13 PM, Lamont Granquist wrote:
> > 
> > > On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> > > 
> > > > How it should be written, i'll look at submitting a PR...
> > > 
> > > Sorry look like I fell victim to thinking that all problems were like my  
> > > last problem.
> > > 
> > > The hostname is getting set at converge time, fairly late, by the  
> > > hostname cookbook. Your node['fqdn'] will be the old hostname throughout  
> > > the whole compile phase of the chef-client run. In your case since you  
> > > control the code it'll be way easier to use the node['set\_fqdn'] attribute  
> > > that you're passing to the hostname cookbook to pass to the  
> > > chef-server cookbook:
> > > 
> > > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > > = "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"
> > > 
> > > If that doesn't work for you then you may have an issue trying to do  
> > > that. The attributes are most likely getting passed into the template  
> > > variable sometime in compiletime and your node['fqdn'] isn't getting  
> > > updated until converge time. Either the hostname cookbook needs to be  
> > > changed to do its work at compile-time or else the chef-server cookbook  
> > > needs to be converted to be lazy.
> > > 
> > > A better approach would probably be for the hostname cookbook to expose  
> > > a ruby library to call to get the desired hostname (basically sugar around  
> > > either returning node['set\_fqdn'] or else returning the output of  
> > > "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'") and then you  
> > > could get that value at compile time and set attributes with it just fine.
> > > 
> > > So, I'd actually suggest doing something more like this than using  
> > > that hostname cookbook:
> > 
> > self.class.send(:include, Chef::Mixin::ShellOut)
> > 
> > # execute very early
> > 
> > execute "set hostname to nodename" do  
> > command "/bin/hostname #{node.name}"  
> > action :nothing  
> > not\_if "shell\_out!('hostname').stdout.chomp == node.name"  
> > end.run\_action(:run)
> > 
> > # fake out ohai data
> > 
> > node.automatic\_attrs["hostname"] = node.name[/[^.]_/]  
> > node.automatic\_attrs["domain"] = node.name[/.(._)/, 1]  
> > node.automatic\_attrs["machinename"] = node.name  
> > node.automatic\_attrs["fqdn"] = node.name
> > 
> > case node["platform\_family"]  
> > when "rhel", "fedora"  
> > template "/etc/sysconfig/network" do  
> > source "redhat-network.erb"  
> > end  
> > when "debian"  
> > template "/etc/hostname" do  
> > source "ubuntu-hostname.erb"  
> > end  
> > end
> > 
> > That encodes my policy that node names are fqdns and that the fqdn is set  
> > from the node name and that hostnames are fqdns. If you have a different  
> > policy, you can modify that code. The important bit is that I set the  
> > hostname of the box at compile time at the top of my run\_list. Then I  
> > override the ohai automatic attrs at compile time so that all later code  
> > will see that. The templates can wait until converge time since those are  
> > only going to be necessary on next boot.
> > 
> > You can quibble with this because clearly there's a problem with  
> > separation of concerns and we "should" be calling ohai to reload the node  
> > data, but if you do that, you need to make sure that you're doing that at  
> > compile time. You could wrap the hostname cookbook's recipe logic in an  
> > LWRP and then simply force that to run at compile time. I don't care about  
> > that because I know what the ohai policy on those attrs are and that we're  
> > unlikely to change it so I'm not too concerned about duplicating the code  
> > and forcing it like that.
> > 
> > And the function of setting the current hostname and fixing the ohai data  
> > is separate from the function of updating the templates. If I was doing  
> > this reusably I'd keep those separate. I'd also keep 'finding the  
> > hostname' separate and probably just put that in a straight up ruby library  
> > function. That would be function or set of functions that you could use to  
> > poke vmware or xenserver or whatever to see what your hostname is set as in  
> > the hypervisor and use that.

--  
Rock Solid Ops: development & operations consulting for Ruby on Rails

---

<div class="post-metadata">

**Author:** ![Tensibai](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tensibai/32/29_2.png) [@Tensibai](https://discourse.chef.io/u/Tensibai)\
**Post date:** [October 11, 2014, 7:13pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/6 "2014-10-11T19:13:17Z")

</div>

My 2cts on the subject: don't really on the hostname, use the serial.number as machine hostname and take advantage of dns aliases (cname) which may be filled in an attribute to be used later (maybe overriding the real fun for other cookbooks)

---- Mathieu Martin a écrit ----

> A lot of people also just sidestep all of this fun by setting the hostname at bootstrap time, before the initial Chef run.
> 
> Although the problem comes back in full, if you need to change the hostname later 🙂
> 
> Mat
> 
> On Thursday, October 9, 2014, Lamont Granquist [lamont@opscode.com](mailto:lamont@opscode.com) wrote:
> 
> "setting the automatic\_attrs" wasn't really the point of that code I pasted there. the point is to execute it at compile time rather than converge time. the code you point to in the system cookbook is inside of a provider and will also get executed at converge time. you can call the system\_hostname LWRP yourself and force it to run at compile time by method chaining .run\_action(:set) off of it (and add an `action :nothing` attribute inside the LWRP).
> 
> On 10/9/14, 8:13 PM, Greg Barker wrote:
> 
> Thanks Lamont. I tried using the system cookbook which seems to do as you have suggested (setting the automatic\_attrs) but it still doesn't work.
> 
> The system cookbook is first in my run list and then towards the end it gets to my recipe which contains:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] = "/etc/pki/tls/certs/#{node['fqdn']}.pem"
> 
> ...but it still thinks node['fqdn'] is localhost, it doesn't get the updated value.
> 
> I guess I will just have to steer clear of relying on node['fqdn'] unless you have any other ideas, it's a bummer that so many cookbooks use it though.
> 
> Greg
> 
> On Sat, Oct 4, 2014 at 10:27 AM, Lamont Granquist [lamont@opscode.com](mailto:lamont@opscode.com) wrote:
> 
> On 10/3/14, 5:13 PM, Lamont Granquist wrote:
> 
> On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> 
> How it should be written, i'll look at submitting a PR...
> 
> Sorry look like I fell victim to thinking that all problems were like my last problem.
> 
> The hostname is getting set at converge time, fairly late, by the hostname cookbook. Your node['fqdn'] will be the old hostname throughout the whole compile phase of the chef-client run. In your case since you control the code it'll be way easier to use the node['set\_fqdn'] attribute that you're passing to the hostname cookbook to pass to the  
> chef-server cookbook:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] = "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"
> 
> If that doesn't work for you then you may have an issue trying to do that. The attributes are most likely getting passed into the template variable sometime in compiletime and your node['fqdn'] isn't getting updated until converge time. Either the hostname cookbook needs to be changed to do its work at compile-time or else the chef-server cookbook needs to be converted to be lazy.
> 
> A better approach would probably be for the hostname cookbook to expose a ruby library to call to get the desired hostname (basically sugar around either returning node['set\_fqdn'] or else returning the output of "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'") and then you could get that value at compile time and set attributes with it just fine.
> 
> So, I'd actually suggest doing something more like this than using that hostname cookbook:
> 
> self.class.send(:include, Chef::Mixin::ShellOut)
> 
> # execute very early
> 
> execute "set hostname to nodename" do  
> command "/bin/hostname #{node.name}"  
> action :nothing  
> not\_if "shell\_out!('hostname').stdout.chomp == node.name"  
> end.run\_action(:run)
> 
> # fake out ohai data
> 
> node.automatic\_attrs["hostname"] = node.name[/[^.]_/]  
> node.automatic\_attrs["domain"] = node.name[/.(._)/, 1]  
> node.automatic\_attrs["machinename"] = node.name  
> node.automatic\_attrs["fqdn"] = node.name
> 
> case node["platform\_family"]  
> when "rhel", "fedora"  
> template "/etc/sysconfig/network" do  
> source "redhat-network.erb"  
> end  
> when "debian"  
> template "/etc/hostname" do  
> source "ubuntu-hostname.erb"  
> end  
> end
> 
> That encodes my policy that node names are fqdns and that the fqdn is set from the node name and that hostnames are fqdns. If you have a different policy, you can modify that code. The important bit is that I set the hostname of the box at compile time at the top of my run\_list. Then I override the ohai automatic attrs at compile time so that all later code will see that. The templates can wait until converge time since those are only going to be necessary on next boot.
> 
> You can quibble with this because clearly there's a problem with separation of concerns and we "should" be calling ohai to reload the node data, but if you do that, you need to make sure that you're doing that at compile time. You could wrap the hostname cookbook's recipe logic in an LWRP and then simply force that to run at compile time. I don't care about that because I know what the ohai policy on those attrs are and that we're unlikely to change it so I'm not too concerned about duplicating the code and forcing it like that.
> 
> And the function of setting the current hostname and fixing the ohai data is separate from the function of updating the templates. If I was doing this reusably I'd keep those separate. I'd also keep 'finding the hostname' separate and probably just put that in a straight up ruby library function. That would be function or set of functions that you could use to poke vmware or xenserver or whatever to see what your hostname is set as in the hypervisor and use that.
> 
> --  
> Rock Solid Ops: development & operations consulting for Ruby on Rails

---

<div class="post-metadata">

**Author:** ![Darren\_Dyke](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/darren_dyke/32/165_2.png) [@Darren\_Dyke](https://discourse.chef.io/u/Darren_Dyke)\
**Post date:** [October 12, 2014, 4:31am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/7 "2014-10-12T04:31:09Z")

</div>

U,ugu,,ag, uyuxa,qqsdsr

Sent from my BlackBerry 10 smartphone on the Verizon Wireless 4G LTE network. **From:** Tensibai Zhaoying **Sent:** Saturday, October 11, 2014 15:13 **To:** [chef@lists.opscode.com](mailto:chef@lists.opscode.com) **Reply To:** [chef@lists.opscode.com](mailto:chef@lists.opscode.com) **Subject:** [chef] Re: Re: How to override node attribute with lazy value?)()(). , g. Gyv},a‎

My 2cts on the subject: don't really on the hostname, u1se the serial.number as machine hostname and take advantage of dns aliases (cname) which may be filled in an attribute to be used later (maybe ov=erriding the real fun for other cookbooks)

---- Mathieu Martin a écrit ----

A lot of people also just sidestep all of this fun by setting the hostname at bootstrap time, before the initial Chef run.

Although the problem comes back in full, if you need to change the hostname later 🙂

Mat

On Thursday, October 9, 2014, Lamont Granquist \<[lamont@opscode.com](mailto:lamont@opscode.com)\> wrote:

> ```
> "setting the automatic_attrs" wasn't really the point of that code
> I pasted there. the point is to execute it at compile time rather
> than converge time. the code you point to in the system cookbook
> is inside of a provider and will also get executed at converge
> time. you can call the system_hostname LWRP yourself and force it
> to run at compile time by method chaining .run_action(:set) off of
> it (and add an `action :nothing` attribute inside the LWRP).
> 
> On 10/9/14, 8:13 PM, Greg Barker wrote:
> 
> ```
> 
> > Thanks Lamont. I tried using the [system](https://github.com/xhost-cookbooks/system) cookbook which seems to do as you have suggested ([setting the automatic\_attrs](https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48)) but it still doesn't work.
> > 
> > ```
> > The system cookbook is first in my run list and then towards
> > the end it gets to my recipe which contains:
> > 
> > ```
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > = "/etc/pki/tls/certs/#{node['fqdn']}.pem"
> > 
> > ```
> > ...but it still thinks node['fqdn'] is localhost, it doesn't
> > get the updated value.
> > 
> > I guess I will just have to steer clear of relying on
> > node['fqdn'] unless you have any other ideas, it's a bummer
> > that so many cookbooks use it though.
> > 
> > Greg
> > 
> > ```
> > 
> > On Sat, Oct 4, 2014 at 10:27 AM, Lamont  
> > Granquist \<lamont@opscode.com\>  
> > wrote:
> > 
> > > On 10/3/14, 5:13 PM, Lamont Granquist wrote:
> > > 
> > > > On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> > > > 
> > > > > ```
> > > > > How it should be written, i'll look at submitting a
> > > > > PR...
> > > > > 
> > > > > ```
> > > > 
> > > > ```
> > > > Sorry look like I fell victim to thinking that all
> > > > problems were like my last problem.
> > > > 
> > > > The hostname is getting set at converge time, fairly
> > > > late, by the hostname cookbook. Your node['fqdn']
> > > > will be the old hostname throughout the whole compile
> > > > phase of the chef-client run. In your case since you
> > > > control the code it'll be way easier to use the
> > > > node['set_fqdn'] attribute that you're passing to the
> > > > hostname cookbook to pass to the
> > > > 
> > > > chef-server cookbook:
> > > > 
> > > > node.override["chef-server"]["configuration"]["nginx"]["ssl_certificate"]
> > > > = "/etc/pki/tls/certs/#{node['set_fqdn']}.pem"
> > > > 
> > > > If that doesn't work for you then you may have an
> > > > issue trying to do that. The attributes are most
> > > > likely getting passed into the template variable
> > > > sometime in compiletime and your node['fqdn'] isn't
> > > > getting updated until converge time. Either the
> > > > hostname cookbook needs to be changed to do its work
> > > > at compile-time or else the chef-server cookbook needs
> > > > to be converted to be lazy.
> > > > 
> > > > A better approach would probably be for the hostname
> > > > cookbook to expose a ruby library to call to get the
> > > > desired hostname (basically sugar around either
> > > > returning node['set_fqdn'] or else returning the
> > > > output of "/usr/sbin/vmtoolsd --cmd 'info-get
> > > > guestinfo.hostname'") and then you could get that
> > > > value at compile time and set attributes with it just
> > > > fine.
> > > > 
> > > > ```
> > > 
> > > So, I'd actually suggest doing something more like this than using that hostname cookbook:
> > > 
> > > ```
> > > self.class.send(:include, Chef::Mixin::ShellOut)
> > > 
> > > # execute very early
> > > 
> > > execute "set hostname to nodename" do
> > > 
> > > command "/bin/hostname #{<a href="http://node.name" target="_blank">node.name</a>}"
> > > 
> > > action :nothing
> > > 
> > > not_if "shell_out!('hostname').stdout.chomp == <a href="http://node.name" target="_blank">node.name</a>"
> > > 
> > > end.run_action(:run)
> > > 
> > > # fake out ohai data
> > > 
> > > node.automatic_attrs["hostname"] = <a href="http://node.name" target="_blank">node.name</a>[/[^\.]*/]
> > > 
> > > node.automatic_attrs["domain"] = <a href="http://node.name" target="_blank">node.name</a>[/\.(.*)/,
> > > 1]
> > > 
> > > node.automatic_attrs["machinename"] = <a href="http://node.name" target="_blank">node.name</a>
> > > 
> > > node.automatic_attrs["fqdn"] = <a href="http://node.name" target="_blank">node.name</a>
> > > 
> > > case node["platform_family"]
> > > 
> > > when "rhel", "fedora"
> > > 
> > > template "/etc/sysconfig/network" do
> > > 
> > > source "redhat-network.erb"
> > > 
> > > end
> > > 
> > > when "debian"
> > > 
> > > template "/etc/hostname" do
> > > 
> > > source "ubuntu-hostname.erb"
> > > 
> > > end
> > > 
> > > end
> > > 
> > > That encodes my policy that node names are fqdns and that
> > > the fqdn is set from the node name and that hostnames are
> > > fqdns. If you have a different policy, you can modify that
> > > code. The important bit is that I set the hostname of the
> > > box at compile time at the top of my run_list. Then I
> > > override the ohai automatic attrs at compile time so that
> > > all later code will see that. The templates can wait until
> > > converge time since those are only going to be necessary on
> > > next boot.
> > > 
> > > You can quibble with this because clearly there's a problem
> > > with separation of concerns and we "should" be calling ohai
> > > to reload the node data, but if you do that, you need to
> > > make sure that you're doing that at compile time. You could
> > > wrap the hostname cookbook's recipe logic in an LWRP and
> > > then simply force that to run at compile time. I don't care
> > > about that because I know what the ohai policy on those
> > > attrs are and that we're unlikely to change it so I'm not
> > > too concerned about duplicating the code and forcing it like
> > > that.
> > > 
> > > And the function of setting the current hostname and fixing
> > > the ohai data is separate from the function of updating the
> > > templates. If I was doing this reusably I'd keep those
> > > separate. I'd also keep 'finding the hostname' separate and
> > > probably just put that in a straight up ruby library
> > > function. That would be function or set of functions that
> > > you could use to poke vmware or xenserver or whatever to see
> > > what your hostname is set as in the hypervisor and use that.
> > > 
> > > ```

--

Rock Solid Ops: development & operations consulting for Ruby on Rails

---

<div class="post-metadata">

**Author:** ![Darren\_Dyke](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/darren_dyke/32/165_2.png) [@Darren\_Dyke](https://discourse.chef.io/u/Darren_Dyke)\
**Post date:** [October 12, 2014, 4:32am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/8 "2014-10-12T04:32:22Z")

</div>

Sent from my BlackBerry 10 smartphone on the Verizon Wireless 4G LTE network. **From:** Mathieu MartinuuGac‎ **Sent:** Saturday, October 11, 2014 14:34 **To:** chef@lists.opscode.com‎ **Reply To:** [chef@lists.opscode.com](mailto:chef@lists.opscode.com) **Cc:** Greg Barker **Subject:** [chef] Re: How to override node attribute with lazy value?

A lot of people also just sidestep all of this fun by setting the hostname at bootstrap time, before the initial Chef run.

Although the problem comes back in full, if you need to change the hostname later 🙂

Mat

On Thursday, October 9, 2014, Lamont Granquist \<[lamont@opscode.com](mailto:lamont@opscode.com)\> wrote:

> ```
> "setting the automatic_attrs" wasn't really the point of that code
> I pasted there. the point is to execute it at compile time rather
> than converge time. the code you point to in the system cookbook
> is inside of a provider and will also get executed at converge
> time. you can call the system_hostname LWRP yourself and force it
> to run at compile time by method chaining .run_action(:set) off of
> it (and add an `action :nothing` attribute inside the LWRP).
> 
> On 10/9/14, 8:13 PM, Greg Barker wrote:
> 
> ```
> 
> > Thanks Lamont. I tried using the [system](https://github.com/xhost-cookbooks/system) cookbook which seems to do as you have suggested ([setting the automatic\_attrs](https://github.com/xhost-cookbooks/system/blob/0564b30052923c9e9d5192c52a6dbe9e8f2f9d7b/providers/hostname.rb#L48)) but it still doesn't work.
> > 
> > ```
> > The system cookbook is first in my run list and then towards
> > the end it gets to my recipe which contains:
> > 
> > ```
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > = "/etc/pki/tls/certs/#{node['fqdn']}.pem"
> > 
> > ```
> > ...but it still thinks node['fqdn'] is localhost, it doesn't
> > get the updated value.
> > 
> > I guess I will just have to steer clear of relying on
> > node['fqdn'] unless you have any other ideas, it's a bummer
> > that so many cookbooks use it though.
> > 
> > Greg
> > 
> > ```
> > 
> > On Sat, Oct 4, 2014 at 10:27 AM, Lamont  
> > Granquist \<lamont@opscode.com\>  
> > wrote:
> > 
> > > On 10/3/14, 5:13 PM, Lamont Granquist wrote:
> > > 
> > > > On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> > > > 
> > > > > ```
> > > > > How it should be written, i'll look at submitting a
> > > > > PR...
> > > > > 
> > > > > ```
> > > > 
> > > > ```
> > > > Sorry look like I fell victim to thinking that all
> > > > problems were like my last problem.
> > > > 
> > > > The hostname is getting set at converge time, fairly
> > > > late, by the hostname cookbook. Your node['fqdn']
> > > > will be the old hostname throughout the whole compile
> > > > phase of the chef-client run. In your case since you
> > > > control the code it'll be way easier to use the
> > > > node['set_fqdn'] attribute that you're passing to the
> > > > hostname cookbook to pass to the
> > > > 
> > > > chef-server cookbook:
> > > > 
> > > > node.override["chef-server"]["configuration"]["nginx"]["ssl_certificate"]
> > > > = "/etc/pki/tls/certs/#{node['set_fqdn']}.pem"
> > > > 
> > > > If that doesn't work for you then you may have an
> > > > issue trying to do that. The attributes are most
> > > > likely getting passed into the template variable
> > > > sometime in compiletime and your node['fqdn'] isn't
> > > > getting updated until converge time. Either the
> > > > hostname cookbook needs to be changed to do its work
> > > > at compile-time or else the chef-server cookbook needs
> > > > to be converted to be lazy.
> > > > 
> > > > A better approach would probably be for the hostname
> > > > cookbook to expose a ruby library to call to get the
> > > > desired hostname (basically sugar around either
> > > > returning node['set_fqdn'] or else returning the
> > > > output of "/usr/sbin/vmtoolsd --cmd 'info-get
> > > > guestinfo.hostname'") and then you could get that
> > > > value at compile time and set attributes with it just
> > > > fine.
> > > > 
> > > > ```
> > > 
> > > So, I'd actually suggest doing something more like this than using that hostname cookbook:
> > > 
> > > ```
> > > self.class.send(:include, Chef::Mixin::ShellOut)
> > > 
> > > # execute very early
> > > 
> > > execute "set hostname to nodename" do
> > > 
> > > command "/bin/hostname #{<a href="http://node.name" target="_blank">node.name</a>}"
> > > 
> > > action :nothing
> > > 
> > > not_if "shell_out!('hostname').stdout.chomp == <a href="http://node.name" target="_blank">node.name</a>"
> > > 
> > > end.run_action(:run)
> > > 
> > > # fake out ohai data
> > > 
> > > node.automatic_attrs["hostname"] = <a href="http://node.name" target="_blank">node.name</a>[/[^\.]*/]
> > > 
> > > node.automatic_attrs["domain"] = <a href="http://node.name" target="_blank">node.name</a>[/\.(.*)/,
> > > 1]
> > > 
> > > node.automatic_attrs["machinename"] = <a href="http://node.name" target="_blank">node.name</a>
> > > 
> > > node.automatic_attrs["fqdn"] = <a href="http://node.name" target="_blank">node.name</a>
> > > 
> > > case node["platform_family"]
> > > 
> > > when "rhel", "fedora"
> > > 
> > > template "/etc/sysconfig/network" do
> > > 
> > > source "redhat-network.erb"
> > > 
> > > end
> > > 
> > > when "debian"
> > > 
> > > template "/etc/hostname" do
> > > 
> > > source "ubuntu-hostname.erb"
> > > 
> > > end
> > > 
> > > end
> > > 
> > > That encodes my policy that node names are fqdns and that
> > > the fqdn is set from the node name and that hostnames are
> > > fqdns. If you have a different policy, you can modify that
> > > code. The important bit is that I set the hostname of the
> > > box at compile time at the top of my run_list. Then I
> > > override the ohai automatic attrs at compile time so that
> > > all later code will see that. The templates can wait until
> > > converge time since those are only going to be necessary on
> > > next boot.
> > > 
> > > You can quibble with this because clearly there's a problem
> > > with separation of concerns and we "should" be calling ohai
> > > to reload the node data, but if you do that, you need to
> > > make sure that you're doing that at compile time. You could
> > > wrap the hostname cookbook's recipe logic in an LWRP and
> > > then simply force that to run at compile time. I don't care
> > > about that because I know what the ohai policy on those
> > > attrs are and that we're unlikely to change it so I'm not
> > > too concerned about duplicating the code and forcing it like
> > > that.
> > > 
> > > And the function of setting the current hostname and fixing
> > > the ohai data is separate from the function of updating the
> > > templates. If I was doing this reusably I'd keep those
> > > separate. I'd also keep 'finding the hostname' separate and
> > > probably just put that in a straight up ruby library
> > > function. That would be function or set of functions that
> > > you could use to poke vmware or xenserver or whatever to see
> > > what your hostname is set as in the hypervisor and use that.
> > > 
> > > ```

--

Rock Solid Ops: development & operations consulting for Ruby on Rails

---

<div class="post-metadata">

**Author:** ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)\
**Post date:** [October 13, 2014, 5:34am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/9 "2014-10-13T05:34:04Z")

</div>

On 10/11/14, 11:33 AM, Mathieu Martin wrote:

> A lot of people also just sidestep all of this fun by setting the  
> hostname at bootstrap time, before the initial Chef run.
> 
> Although the problem comes back in full, if you need to change the  
> hostname later 🙂

Yeah setting the identity of the server (in general) needs to be pushed  
as early as possible (in general), or you're going to have a bad time.

---

<div class="post-metadata">

**Author:** ![fletchowns](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/fletchowns/32/53_2.png) [@fletchowns](https://discourse.chef.io/u/fletchowns)\
**Post date:** [October 2, 2014, 6:18pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/10 "2014-10-02T18:18:55Z")

</div>

Thanks Noah. I tried it out but I don't think I'm doing it right.

node["chef-server"]["configuration"]["nginx"] % { ssl\_certificate:  
"/etc/pki/tls/certs/#{node[:fqdn]}.pem" }

This resulted in:

NoMethodError - undefined method `%' for nil:NilClass

So before that line I added:

node.default["chef-server"]["configuration"]["nginx"] = {}

But now I get the error:

NoMethodError - Undefined node attribute or method `%' on `node'

Any ideas?

On Thu, Oct 2, 2014 at 7:55 AM, Noah Kantrowitz [noah@coderanger.net](mailto:noah@coderanger.net) wrote:

> On Oct 2, 2014, at 3:13 AM, Greg Barker [fletch@fletchowns.net](mailto:fletch@fletchowns.net) wrote:
> 
> > The chef-server readme shows how to override nginx attributes. However,  
> > it doesn't seem to work like I want it to when I do:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> "/etc/pki/tls/certs/#{node[:fqdn]}.pem"
> 
> > node[:fqdn] is being updated during my chef run using the hostname  
> > cookbook, and so using the above results in an error because chef-server  
> > ends up looking for /etc/pki/tls/certs/localhost.pem (the old hostname),  
> > when it should instead be using /etc/pki/tls/certs/mynode.mycompany.com.pem.
> > 
> > So I think I want something like the following, but this doesn't work.  
> > What's the right way to do it?
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> lazy { "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> 
> lazy{} is a feature of resources, not of node attributes. See  
> [Derived Attributes in Chef – Noah Kantrowitz](https://coderanger.net/derived-attributes/) for more information about  
> how to handle delayed interpolation in node attributes.
> 
> --Noah

---

<div class="post-metadata">

**Author:** ![Christine\_Draper](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/christine_draper/32/68_2.png) [@Christine\_Draper](https://discourse.chef.io/u/Christine_Draper)\
**Post date:** [October 3, 2014, 2:21pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/11 "2014-10-03T14:21:32Z")

</div>

Greg,

Using Noah's approach, you'd have something like this in your attribute  
file, to establish the pattern for the derived attribute:

node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
"/etc/pki/tls/certs/%{fqdn}.pem" }

And then this in your recipe where actually wanted to realize the value:

node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % { fqdn  
: node[:fqdn] }

Hope this helps.  
Christine

"/etc/pki/tls/certs/#{node[:fqdn]}.pem" }

On Thu, Oct 2, 2014 at 11:18 AM, Greg Barker [fletch@fletchowns.net](mailto:fletch@fletchowns.net) wrote:

> Thanks Noah. I tried it out but I don't think I'm doing it right.
> 
> node["chef-server"]["configuration"]["nginx"] % { ssl\_certificate:  
> "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> 
> This resulted in:
> 
> NoMethodError - undefined method `%' for nil:NilClass
> 
> So before that line I added:
> 
> node.default["chef-server"]["configuration"]["nginx"] = {}
> 
> But now I get the error:
> 
> NoMethodError - Undefined node attribute or method `%' on `node'
> 
> Any ideas?
> 
> On Thu, Oct 2, 2014 at 7:55 AM, Noah Kantrowitz [noah@coderanger.net](mailto:noah@coderanger.net)  
> wrote:
> 
> > On Oct 2, 2014, at 3:13 AM, Greg Barker [fletch@fletchowns.net](mailto:fletch@fletchowns.net) wrote:
> > 
> > > The chef-server readme shows how to override nginx attributes. However,  
> > > it doesn't seem to work like I want it to when I do:
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> > "/etc/pki/tls/certs/#{node[:fqdn]}.pem"
> > 
> > > node[:fqdn] is being updated during my chef run using the hostname  
> > > cookbook, and so using the above results in an error because chef-server  
> > > ends up looking for /etc/pki/tls/certs/localhost.pem (the old hostname),  
> > > when it should instead be using /etc/pki/tls/certs/mynode.mycompany.com.pem.
> > > 
> > > So I think I want something like the following, but this doesn't work.  
> > > What's the right way to do it?
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> > lazy { "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> > 
> > lazy{} is a feature of resources, not of node attributes. See  
> > [Derived Attributes in Chef – Noah Kantrowitz](https://coderanger.net/derived-attributes/) for more information about  
> > how to handle delayed interpolation in node attributes.
> > 
> > --Noah

---

<div class="post-metadata">

**Author:** ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)\
**Post date:** [October 3, 2014, 3:02pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/12 "2014-10-03T15:02:45Z")

</div>

Just move that into a computation in recipe code that is stored in a  
variable and not in a node attribute:

in default.rb:

ssl\_certificate = node["chef-server"]["configuration"]["nginx"][  
"ssl\_certificate"] ||=  
"/etc/pki/tls/certs/%{node["fqdn"]}.pem"

then don't set that attribute in the attribute file, leave it only as a  
hook for someone to override the computation with.

See [GitHub - lamont-cookbooks/erlang\_one: Example computed attributes without using an attribute repo](https://github.com/lamont-granquist/erlang_one) for an example  
cookbook I wrote last night, with tests showing that you can wrap the  
cookbook the way that people want to. Works without computed attributes  
directly in the attributes file, it exposes the kind of behavior so that  
what the recipe does is computed from the input attributes. Since it  
uses a ruby variable instead of setting node attributes in recipe code  
there's no attribute precedence issues.

On Fri Oct 3 07:21:32 2014, Christine Draper wrote:

> Greg,
> 
> Using Noah's approach, you'd have something like this in your  
> attribute file, to establish the pattern for the derived attribute:
> 
> node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> "/etc/pki/tls/certs/%{fqdn}.pem" }
> 
> And then this in your recipe where actually wanted to realize the value:
> 
> node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % {  
> fqdn : node[:fqdn] }
> 
> Hope this helps.  
> Christine
> 
> "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> 
> On Thu, Oct 2, 2014 at 11:18 AM, Greg Barker \<[fletch@fletchowns.net](mailto:fletch@fletchowns.net)  
> [mailto:fletch@fletchowns.net](mailto:fletch@fletchowns.net)\> wrote:
> 
> Thanks Noah. I tried it out but I don't think I'm doing it right.
> 
> node["chef-server"]["configuration"]["nginx"] % { ssl\_certificate:  
> "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> 
> This resulted in:
> 
> NoMethodError - undefined method `%' for nil:NilClass
> 
> So before that line I added:
> 
> node.default["chef-server"]["configuration"]["nginx"] = {}
> 
> But now I get the error:
> 
> NoMethodError - Undefined node attribute or method `%' on `node'
> 
> Any ideas?
> 
> On Thu, Oct 2, 2014 at 7:55 AM, Noah Kantrowitz  
> \<[noah@coderanger.net](mailto:noah@coderanger.net) [mailto:noah@coderanger.net](mailto:noah@coderanger.net)\> wrote:
> 
> On Oct 2, 2014, at 3:13 AM, Greg Barker \<[fletch@fletchowns.net](mailto:fletch@fletchowns.net)  
> [mailto:fletch@fletchowns.net](mailto:fletch@fletchowns.net)\> wrote:
> 
> > The chef-server readme shows how to override nginx  
> > attributes. However, it doesn't seem to work like I want it to  
> > when I do:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> = "/etc/pki/tls/certs/#{node[:fqdn]}.pem"
> 
> > node[:fqdn] is being updated during my chef run using the  
> > hostname cookbook, and so using the above results in an error  
> > because chef-server ends up looking for  
> > /etc/pki/tls/certs/localhost.pem (the old hostname), when it  
> > should instead be using  
> > /etc/pki/tls/certs/mynode.mycompany.com.pem.
> > 
> > So I think I want something like the following, but this  
> > doesn't work. What's the right way to do it?
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> = lazy { "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> 
> lazy{} is a feature of resources, not of node attributes. See  
> [Derived Attributes in Chef – Noah Kantrowitz](https://coderanger.net/derived-attributes/) for more  
> information about how to handle delayed interpolation in node  
> attributes.
> 
> --Noah

---

<div class="post-metadata">

**Author:** ![fletchowns](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/fletchowns/32/53_2.png) [@fletchowns](https://discourse.chef.io/u/fletchowns)\
**Post date:** [October 3, 2014, 10:05pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/13 "2014-10-03T22:05:03Z")

</div>

Thanks for the additional responses. Unfortunately I still wasn't able to  
get it working.

I put the following in my attributes/default.rb:

default["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
"/etc/pki/tls/certs/%{fqdn}.pem"  
default["chef-server"]["configuration"]["nginx"]["ssl\_certificate\_key"] =  
"/etc/pki/tls/private/%{fqdn}.key"

Then in my recipe I have:

node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % { fqdn:  
node[:fqdn] }  
node["chef-server"]["configuration"]["nginx"]["ssl\_certificate\_key"] % {  
fqdn: node[:fqdn] }

include\_recipe "chef-server::default"

This resulted in a /var/opt/chef-server/nginx/etc/chef\_https\_lb.conf with:

ssl\_certificate /etc/pki/tls/certs/%{fqdn}.pem;  
ssl\_certificate\_key /etc/pki/tls/private/%{fqdn}.key;

Which of course nginx did not like:

2014-10-03\_21:59:37.09937 nginx: [emerg] directive "ssl\_certificate" is not  
terminated by ";"

I also tried setting those attributes in my role instead of the  
attributes/default.rb file:

"configuration": {  
"nginx": {  
"ssl\_certificate": "/etc/pki/tls/certs/%{fqdn}.pem",  
"ssl\_certificate\_key": "/etc/pki/tls/private/%{fqdn}.key"  
}  
}

This resulted in the same error.

Lamont - I'm not sure I understand your response. Does that actually set  
the node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
attribute that the chef-server cookbook is expecting? Or is that how the  
chef-server cookbook should have been written?

Thanks,  
Greg

On Fri, Oct 3, 2014 at 8:02 AM, Lamont Granquist [lamont@opscode.com](mailto:lamont@opscode.com) wrote:

> Just move that into a computation in recipe code that is stored in a  
> variable and not in a node attribute:
> 
> in default.rb:
> 
> ssl\_certificate = node["chef-server"]["configuration"]["nginx"][  
> "ssl\_certificate"] ||=  
> "/etc/pki/tls/certs/%{node["fqdn"]}.pem"
> 
> then don't set that attribute in the attribute file, leave it only as a  
> hook for someone to override the computation with.
> 
> See [GitHub - lamont-cookbooks/erlang\_one: Example computed attributes without using an attribute repo](https://github.com/lamont-granquist/erlang_one) for an example  
> cookbook I wrote last night, with tests showing that you can wrap the  
> cookbook the way that people want to. Works without computed attributes  
> directly in the attributes file, it exposes the kind of behavior so that  
> what the recipe does is computed from the input attributes. Since it uses  
> a ruby variable instead of setting node attributes in recipe code there's  
> no attribute precedence issues.
> 
> On Fri Oct 3 07:21:32 2014, Christine Draper wrote:
> 
> > Greg,
> > 
> > Using Noah's approach, you'd have something like this in your  
> > attribute file, to establish the pattern for the derived attribute:
> > 
> > node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> > "/etc/pki/tls/certs/%{fqdn}.pem" }
> > 
> > And then this in your recipe where actually wanted to realize the value:
> > 
> > node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % {  
> > fqdn : node[:fqdn] }
> > 
> > Hope this helps.  
> > Christine
> > 
> > "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> > 
> > On Thu, Oct 2, 2014 at 11:18 AM, Greg Barker \<[fletch@fletchowns.net](mailto:fletch@fletchowns.net)  
> > [mailto:fletch@fletchowns.net](mailto:fletch@fletchowns.net)\> wrote:
> > 
> > Thanks Noah. I tried it out but I don't think I'm doing it right.
> > 
> > node["chef-server"]["configuration"]["nginx"] % { ssl\_certificate:  
> > "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> > 
> > This resulted in:
> > 
> > NoMethodError - undefined method `%' for nil:NilClass
> > 
> > So before that line I added:
> > 
> > node.default["chef-server"]["configuration"]["nginx"] = {}
> > 
> > But now I get the error:
> > 
> > NoMethodError - Undefined node attribute or method `%' on `node'
> > 
> > Any ideas?
> > 
> > On Thu, Oct 2, 2014 at 7:55 AM, Noah Kantrowitz  
> > \<[noah@coderanger.net](mailto:noah@coderanger.net) [mailto:noah@coderanger.net](mailto:noah@coderanger.net)\> wrote:
> > 
> > On Oct 2, 2014, at 3:13 AM, Greg Barker \<[fletch@fletchowns.net](mailto:fletch@fletchowns.net)  
> > [mailto:fletch@fletchowns.net](mailto:fletch@fletchowns.net)\> wrote:
> > 
> > > The chef-server readme shows how to override nginx  
> > > attributes. However, it doesn't seem to work like I want it to  
> > > when I do:
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > = "/etc/pki/tls/certs/#{node[:fqdn]}.pem"
> > 
> > > node[:fqdn] is being updated during my chef run using the  
> > > hostname cookbook, and so using the above results in an error  
> > > because chef-server ends up looking for  
> > > /etc/pki/tls/certs/localhost.pem (the old hostname), when it  
> > > should instead be using  
> > > /etc/pki/tls/certs/mynode.mycompany.com.pem.
> > > 
> > > So I think I want something like the following, but this  
> > > doesn't work. What's the right way to do it?
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > = lazy { "/etc/pki/tls/certs/#{node[:fqdn]}.pem" }
> > 
> > lazy{} is a feature of resources, not of node attributes. See  
> > [Derived Attributes in Chef – Noah Kantrowitz](https://coderanger.net/derived-attributes/) for more  
> > information about how to handle delayed interpolation in node  
> > attributes.
> > 
> > --Noah

---

<div class="post-metadata">

**Author:** ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)\
**Post date:** [October 3, 2014, 11:39pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/14 "2014-10-03T23:39:36Z")

</div>

How it should be written, i'll look at submitting a PR...

On Fri Oct 3 15:05:03 2014, Greg Barker wrote:

> Thanks for the additional responses. Unfortunately I still wasn't able  
> to get it working.
> 
> I put the following in my attributes/default.rb:
> 
> default["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] =  
> "/etc/pki/tls/certs/%{fqdn}.pem"  
> default["chef-server"]["configuration"]["nginx"]["ssl\_certificate\_key"] =  
> "/etc/pki/tls/private/%{fqdn}.key"
> 
> Then in my recipe I have:
> 
> node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % {  
> fqdn: node[:fqdn] }  
> node["chef-server"]["configuration"]["nginx"]["ssl\_certificate\_key"] %  
> { fqdn: node[:fqdn] }
> 
> include\_recipe "chef-server::default"
> 
> This resulted in a /var/opt/chef-server/nginx/etc/chef\_https\_lb.conf with:
> 
> ssl\_certificate /etc/pki/tls/certs/%{fqdn}.pem;  
> ssl\_certificate\_key /etc/pki/tls/private/%{fqdn}.key;
> 
> Which of course nginx did not like:
> 
> 2014-10-03\_21:59:37.09937 nginx: [emerg] directive "ssl\_certificate"  
> is not terminated by ";"
> 
> I also tried setting those attributes in my role instead of the  
> attributes/default.rb file:
> 
> "configuration": {  
> "nginx": {  
> "ssl\_certificate": "/etc/pki/tls/certs/%{fqdn}.pem",  
> "ssl\_certificate\_key": "/etc/pki/tls/private/%{fqdn}.key"  
> }  
> }
> 
> This resulted in the same error.
> 
> Lamont - I'm not sure I understand your response. Does that actually  
> set the node["chef-server"]["configuration"]["nginx"][  
> "ssl\_certificate"] attribute that the chef-server cookbook is  
> expecting? Or is that how the chef-server cookbook should have been  
> written?
> 
> Thanks,  
> Greg
> 
> On Fri, Oct 3, 2014 at 8:02 AM, Lamont Granquist \<[lamont@opscode.com](mailto:lamont@opscode.com)  
> [mailto:lamont@opscode.com](mailto:lamont@opscode.com)\> wrote:
> 
> ```
> Just move that into a computation in recipe code that is stored in
> a variable and not in a node attribute:
> 
> in default.rb:
> 
> ssl_certificate = node["chef-server"]["__configuration"]["nginx"][
> "ssl_certificate"] ||=
> "/etc/pki/tls/certs/%{node["__fqdn"]}.pem"
> 
> then don't set that attribute in the attribute file, leave it only
> as a hook for someone to override the computation with.
> 
> See https://github.com/lamont-__granquist/erlang_one
> <https://github.com/lamont-granquist/erlang_one> for an example
> cookbook I wrote last night, with tests showing that you can wrap
> the cookbook the way that people want to. Works without computed
> attributes directly in the attributes file, it exposes the kind of
> behavior so that what the recipe does is computed from the input
> attributes. Since it uses a ruby variable instead of setting node
> attributes in recipe code there's no attribute precedence issues.
> 
> On Fri Oct 3 07:21:32 2014, Christine Draper wrote:
> 
> Greg,
> 
> Using Noah's approach, you'd have something like this in your
> attribute file, to establish the pattern for the derived
> attribute:
> 
> node["chef-server"]["__configuration"]["nginx"][
> "ssl_certificate"] =
> "/etc/pki/tls/certs/%{fqdn}.__pem" }
> 
> And then this in your recipe where actually wanted to realize
> the value:
> 
> node["chef-server"]["__configuration"]["nginx"][
> "ssl_certificate"] % {
> fqdn : node[:fqdn] }
> 
> Hope this helps.
> Christine
> 
> "/etc/pki/tls/certs/#{node[:__fqdn]}.pem" }
> 
> On Thu, Oct 2, 2014 at 11:18 AM, Greg Barker
> <fletch@fletchowns.net <mailto:fletch@fletchowns.net>
> <mailto:fletch@fletchowns.net
> <mailto:fletch@fletchowns.net>>__> wrote:
> 
> Thanks Noah. I tried it out but I don't think I'm doing it right.
> 
> node["chef-server"]["__configuration"]["nginx"] % {
> ssl_certificate:
> "/etc/pki/tls/certs/#{node[:__fqdn]}.pem" }
> 
> This resulted in:
> 
> NoMethodError - undefined method `%' for nil:NilClass
> 
> So before that line I added:
> 
> node.default["chef-server"]["__configuration"]["nginx"] = {}
> 
> But now I get the error:
> 
> NoMethodError - Undefined node attribute or method `%' on `node'
> 
> Any ideas?
> 
> On Thu, Oct 2, 2014 at 7:55 AM, Noah Kantrowitz
> <noah@coderanger.net <mailto:noah@coderanger.net>
> <mailto:noah@coderanger.net <mailto:noah@coderanger.net>>> wrote:
> 
> On Oct 2, 2014, at 3:13 AM, Greg Barker <fletch@fletchowns.net
> <mailto:fletch@fletchowns.net>
> <mailto:fletch@fletchowns.net
> <mailto:fletch@fletchowns.net>>__> wrote:
> 
> > The chef-server readme shows how to override nginx
> attributes. However, it doesn't seem to work like I want it to
> when I do:
> >
> >
> node.override["chef-server"]["__configuration"]["nginx"]["ssl___certificate"]
> = "/etc/pki/tls/certs/#{node[:__fqdn]}.pem"
> >
> > node[:fqdn] is being updated during my chef run using the
> hostname cookbook, and so using the above results in an error
> because chef-server ends up looking for
> /etc/pki/tls/certs/localhost.__pem (the old hostname), when it
> should instead be using
> /etc/pki/tls/certs/mynode.__mycompany.com.pem.
> >
> > So I think I want something like the following, but this
> doesn't work. What's the right way to do it?
> >
> >
> node.override["chef-server"]["__configuration"]["nginx"]["ssl___certificate"]
> = lazy { "/etc/pki/tls/certs/#{node[:__fqdn]}.pem" }
> 
> lazy{} is a feature of resources, not of node attributes. See
> https://coderanger.net/__derived-attributes/
> <https://coderanger.net/derived-attributes/> for more
> information about how to handle delayed interpolation in node
> attributes.
> 
> --Noah
> 
> ```

---

<div class="post-metadata">

**Author:** ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)\
**Post date:** [October 4, 2014, 12:13am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/15 "2014-10-04T00:13:06Z")

</div>

On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:

> How it should be written, i'll look at submitting a PR...

Sorry look like I fell victim to thinking that all problems were like  
my last problem.

The hostname is getting set at converge time, fairly late, by the  
hostname cookbook. Your node['fqdn'] will be the old hostname  
throughout the whole compile phase of the chef-client run. In your  
case since you control the code it'll be way easier to use the  
node['set\_fqdn'] attribute that you're passing to the hostname cookbook  
to pass to the  
chef-server cookbook:

node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
= "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"

If that doesn't work for you then you may have an issue trying to do  
that. The attributes are most likely getting passed into the template  
variable sometime in compiletime and your node['fqdn'] isn't getting  
updated until converge time. Either the hostname cookbook needs to be  
changed to do its work at compile-time or else the chef-server cookbook  
needs to be converted to be lazy.

A better approach would probably be for the hostname cookbook to expose  
a ruby library to call to get the desired hostname (basically sugar  
around either returning node['set\_fqdn'] or else returning the output  
of "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'") and then  
you could get that value at compile time and set attributes with it  
just fine.

---

<div class="post-metadata">

**Author:** ![Mathieu\_Martin](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/mathieu_martin/32/60_2.png) [@Mathieu\_Martin](https://discourse.chef.io/u/Mathieu_Martin)\
**Post date:** [October 4, 2014, 1:40am UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/16 "2014-10-04T01:40:04Z")

</div>

Greg, just to make sure, since we don't see how you're using that  
interpolation:

node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % { fqdn:  
node[:fqdn] }

This ^ line of Ruby code returns the string you're looking for. It doesn't  
modify the string stored in your attribute.

In other words, this whole line should either be assigned to a variable, or  
be right in your template, like:

ssl\_certificate \<%=  
node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
% { fqdn: node[:fqdn] } %\>;

Is that how you were using this?

Mat

On Fri, Oct 3, 2014 at 8:13 PM, Lamont Granquist [lamont@opscode.com](mailto:lamont@opscode.com) wrote:

> On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> 
> > How it should be written, i'll look at submitting a PR...
> 
> Sorry look like I fell victim to thinking that all problems were like my  
> last problem.
> 
> The hostname is getting set at converge time, fairly late, by the hostname  
> cookbook. Your node['fqdn'] will be the old hostname throughout the whole  
> compile phase of the chef-client run. In your case since you control the  
> code it'll be way easier to use the node['set\_fqdn'] attribute that you're  
> passing to the hostname cookbook to pass to the  
> chef-server cookbook:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> = "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"
> 
> If that doesn't work for you then you may have an issue trying to do  
> that. The attributes are most likely getting passed into the template  
> variable sometime in compiletime and your node['fqdn'] isn't getting  
> updated until converge time. Either the hostname cookbook needs to be  
> changed to do its work at compile-time or else the chef-server cookbook  
> needs to be converted to be lazy.
> 
> A better approach would probably be for the hostname cookbook to expose a  
> ruby library to call to get the desired hostname (basically sugar around  
> either returning node['set\_fqdn'] or else returning the output of  
> "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'") and then you  
> could get that value at compile time and set attributes with it just fine.

--

Organizer of DevOpsMtl [http://www.devopsmtl.com](http://www.devopsmtl.com). @webmat  
[http://twitter.com/webmat](http://twitter.com/webmat), LinkedIn  
[http://ca.linkedin.com/in/mathieumartin/](http://ca.linkedin.com/in/mathieumartin/), blog  
[http://www.programblings.com?utm\_source=email+signature](http://www.programblings.com?utm_source=email+signature).

---

<div class="post-metadata">

**Author:** ![fletchowns](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/fletchowns/32/53_2.png) [@fletchowns](https://discourse.chef.io/u/fletchowns)\
**Post date:** [October 4, 2014, 4:40pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/17 "2014-10-04T16:40:37Z")

</div>

Mathieu, it's the opacide chef-server cookbook that ends up using this  
attribute. That's the problem. 🙂

On Friday, October 3, 2014, Mathieu Martin [webmat@gmail.com](mailto:webmat@gmail.com) wrote:

> Greg, just to make sure, since we don't see how you're using that  
> interpolation:
> 
> node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"] % {  
> fqdn: node[:fqdn] }
> 
> This ^ line of Ruby code returns the string you're looking for. It doesn't  
> modify the string stored in your attribute.
> 
> In other words, this whole line should either be assigned to a variable,  
> or be right in your template, like:
> 
> ssl\_certificate \<%= node["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> % { fqdn: node[:fqdn] } %\>;
> 
> Is that how you were using this?
> 
> Mat
> 
> On Fri, Oct 3, 2014 at 8:13 PM, Lamont Granquist \<[lamont@opscode.com](mailto:lamont@opscode.com)  
> \<javascript:\_e(%7B%7D,'cvml','lamont@opscode.com');\>\> wrote:
> 
> > On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> > 
> > > How it should be written, i'll look at submitting a PR...
> > 
> > Sorry look like I fell victim to thinking that all problems were like my  
> > last problem.
> > 
> > The hostname is getting set at converge time, fairly late, by the  
> > hostname cookbook. Your node['fqdn'] will be the old hostname throughout  
> > the whole compile phase of the chef-client run. In your case since you  
> > control the code it'll be way easier to use the node['set\_fqdn'] attribute  
> > that you're passing to the hostname cookbook to pass to the  
> > chef-server cookbook:
> > 
> > node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> > = "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"
> > 
> > If that doesn't work for you then you may have an issue trying to do  
> > that. The attributes are most likely getting passed into the template  
> > variable sometime in compiletime and your node['fqdn'] isn't getting  
> > updated until converge time. Either the hostname cookbook needs to be  
> > changed to do its work at compile-time or else the chef-server cookbook  
> > needs to be converted to be lazy.
> > 
> > A better approach would probably be for the hostname cookbook to expose a  
> > ruby library to call to get the desired hostname (basically sugar around  
> > either returning node['set\_fqdn'] or else returning the output of  
> > "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'") and then you  
> > could get that value at compile time and set attributes with it just fine.
> 
> --
> 
> Organizer of DevOpsMtl [http://www.devopsmtl.com](http://www.devopsmtl.com). @webmat  
> [http://twitter.com/webmat](http://twitter.com/webmat), LinkedIn  
> [http://ca.linkedin.com/in/mathieumartin/](http://ca.linkedin.com/in/mathieumartin/), blog  
> [http://www.programblings.com?utm\_source=email+signature](http://www.programblings.com?utm_source=email+signature).

---

<div class="post-metadata">

**Author:** ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)\
**Post date:** [October 4, 2014, 5:27pm UTC](https://discourse.chef.io/t/how-to-override-node-attribute-with-lazy-value/5889/18 "2014-10-04T17:27:40Z")

</div>

On 10/3/14, 5:13 PM, Lamont Granquist wrote:

> On Fri Oct 3 16:39:36 2014, Lamont Granquist wrote:
> 
> > How it should be written, i'll look at submitting a PR...
> 
> Sorry look like I fell victim to thinking that all problems were like  
> my last problem.
> 
> The hostname is getting set at converge time, fairly late, by the  
> hostname cookbook. Your node['fqdn'] will be the old hostname  
> throughout the whole compile phase of the chef-client run. In your  
> case since you control the code it'll be way easier to use the  
> node['set\_fqdn'] attribute that you're passing to the hostname  
> cookbook to pass to the  
> chef-server cookbook:
> 
> node.override["chef-server"]["configuration"]["nginx"]["ssl\_certificate"]  
> = "/etc/pki/tls/certs/#{node['set\_fqdn']}.pem"
> 
> If that doesn't work for you then you may have an issue trying to do  
> that. The attributes are most likely getting passed into the template  
> variable sometime in compiletime and your node['fqdn'] isn't getting  
> updated until converge time. Either the hostname cookbook needs to  
> be changed to do its work at compile-time or else the chef-server  
> cookbook needs to be converted to be lazy.
> 
> A better approach would probably be for the hostname cookbook to  
> expose a ruby library to call to get the desired hostname (basically  
> sugar around either returning node['set\_fqdn'] or else returning the  
> output of "/usr/sbin/vmtoolsd --cmd 'info-get guestinfo.hostname'")  
> and then you could get that value at compile time and set attributes  
> with it just fine.

So, I'd actually suggest doing something more like this than using that  
hostname cookbook:

self.class.send(:include, Chef::Mixin::ShellOut)

# execute very early

execute "set hostname to nodename" do  
command "/bin/hostname #{node.name}"  
action :nothing  
not\_if "shell\_out!('hostname').stdout.chomp == node.name"  
end.run\_action(:run)

# fake out ohai data

node.automatic\_attrs["hostname"] = node.name[/[^.]_/]  
node.automatic\_attrs["domain"] = node.name[/.(._)/, 1]  
node.automatic\_attrs["machinename"] = node.name  
node.automatic\_attrs["fqdn"] = node.name

case node["platform\_family"]  
when "rhel", "fedora"  
template "/etc/sysconfig/network" do  
source "redhat-network.erb"  
end  
when "debian"  
template "/etc/hostname" do  
source "ubuntu-hostname.erb"  
end  
end

That encodes my policy that node names are fqdns and that the fqdn is  
set from the node name and that hostnames are fqdns. If you have a  
different policy, you can modify that code. The important bit is that I  
set the hostname of the box at compile time at the top of my run\_list.  
Then I override the ohai automatic attrs at compile time so that all  
later code will see that. The templates can wait until converge time  
since those are only going to be necessary on next boot.

You can quibble with this because clearly there's a problem with  
separation of concerns and we "should" be calling ohai to reload the  
node data, but if you do that, you need to make sure that you're doing  
that at compile time. You could wrap the hostname cookbook's recipe  
logic in an LWRP and then simply force that to run at compile time. I  
don't care about that because I know what the ohai policy on those attrs  
are and that we're unlikely to change it so I'm not too concerned about  
duplicating the code and forcing it like that.

And the function of setting the current hostname and fixing the ohai  
data is separate from the function of updating the templates. If I was  
doing this reusably I'd keep those separate. I'd also keep 'finding the  
hostname' separate and probably just put that in a straight up ruby  
library function. That would be function or set of functions that you  
could use to poke vmware or xenserver or whatever to see what your  
hostname is set as in the hypervisor and use that.
