Best Practice for setting unique Chef Node Attributes
chef-infra
Solution
I see some problems:
- during `knife node edit`, you can't set the attribute as a top-level attribute next to fqdn etc. You have to place it below `normal`. This is the hierarchy between `default` and `override`. See Attribute Precedence
- using `knife node edit` smells. I'd rather not do this (might be okay for the host name, but for everything else it's impossible to track such changes in version control). Try to get the `hostname` cookbook running instead.
- writing attributes out to a `chef.json` file should be IMHO also avoided. Your logic should be inside your cookbooks
- you should have a `base` role / cookbook or similar that includes the trivial things that every node has (like `ntp`, `chef-client` and also the hostname).
- you can set the environment also directly during bootstrapping: `-E myenv` (but yes, I'm wondering why this isn't documented)
- you can set the node name during bootstrapping, too: `-N NAME` or `--node-name NAME`.
Problem
I am attempting to use Chef to manage new virtual machines. I'm using a dedicated Chef server and doing all this work from a separate workstation vm. The way I am currently doing it is cloning a base vm image then using knife bootstrap to install Chef and bring the vm to a consistent state. I can specify an environment or run list for the vm; I can override certain settings in my environment, e.g. I have the chef-client interval in the "overrides" block of the test environment set to run the client every 60 while I'm testing so I don't have to manually run chef-client every time. For instance, my workflow is this: clone vm template and start vm set the hostname manually (update /etc/hostname and /etc/hosts) and reboot Bootstrap the node with the initial recipes knife bootstrap chef-test1 -r 'recipe[ntp],recipe[chef-client]' edit the node to reflect the new environment The problem I am having is setting per-node attributes. I would like to use the hostname cookbook to set the node's hostname, if I set this in a role then each server would have to have a new role created. But when I attempt to bootstrap and include this role I get an error: ``` chef-test1 * log[Please set the set_fqdn attribute to desired hostname] action write[2013-12-09T16:26:56-07:00] WARN: Please set the set_fqdn attribute to desired hostname ``` When I bootstrap without that recipe and attempt to edit the node and set the "set_fqdn" attribute, I am unable to save the attribute, e.g. this json: ``` { "name": "chef-test1", "set_fqdn": "chef-test1.local.fqdn", "chef_environment": "test-dev1", "normal": { "tags": [ ] }, "run_list": [ "recipe[ntp]", "recipe[chef-client]", "recipe[hostname]" ] } ``` when I exit out of my editor, knife tells me: ``` Node not updated, skipping node save ``` I attempted to edit this attribute in the chef gui and the attribute won't save. I found this guy who is creating the json in /etc/chef/chef.json, doing basically what I would expect, but I'm not sure how /etc/chef/chef.json comes into play (update it for each new node? I'm not using chef-solo so maybe that's where my confusion is). According to this email thread it's not possible to override default attributes with knife node edit, but "set_fqdn" isn't a default. I would like to avoid creating a role for each node, and I think I can use the hostname cookbook to alleviate the need to manually set the hostname, something like: knife bootstrap saucy64 -r 'recipe[ntp],recipe[chef-client],recipe[hostname]' --json '"{ set_fqdn": "chef-test1.local.tld", "chef_client": { "interval": "600" }' knife bootstrap fedora19 -r 'recipe[ntp],recipe[chef-client],recipe[hostname]' --json '"{ set_fqdn": "chef-test2.local.tld", "chef_client": { "interval": "60" }' I appreciate the assistance.