Contributors20 minutes | Key points: - You ran
knife bootstrap to associate your node with the Chef server and do an initial check-in. Bootstrapping is a one-time process. - The
knife winrm command enables you to update your node's configuration when your cookbook changes.
|
During the bootstrap process, your node downloaded and installed chef-client, downloaded the latest cookbooks, and executed the run-list.
Chef provides information about your node that you can access from your cookbooks. Here you'll update the home page to display your node's fully-qualified domain name (FQDN). You'll practice updating your cookbook, uploading it to the Chef server, and seeing the changes appear on your node.
You already learned how to use the template resource to reference the HTML file for your home page. You're ready to add placeholders to your HTML file that are filled in with info about your node as the recipe runs.
1. Add template code to your HTML
When you bootstrapped your node, the Chef server created what's called a node object for you. This node object contains a number of attributes that describe the node, and these attributes are saved on the Chef server. When a recipe runs, a node object is loaded into the program. Chef loads the node's attributes from the Chef server into memory. You can access these attributes from your Chef recipes.
For our home page, we want to display the server's fully qualified domain name (FQDN). To do so, we access the fqdn attribute of the node object. On the local workstation copy of your learn_chef_iis cookbook, change Default.htm.erb to look like this.
Editor: ~/learn-chef/cookbooks/learn_chef_iis/templates/Default.htm.erb
1
2
3
4
5
| <html>
<body>
<h1>hello from <%= node['fqdn'] %></h1>
</body>
</html> |
The <%= %> syntax enables you to provide placeholders in your template file. Placeholders are replaced with their values when chef-client runs. You'll work more with templates in future modules, but you can read more now in the Chef documentation.
| Keep in mind that this example is for illustrative purposes. In practice, you might modify your web server's configuration file to specify the server's hostname or other info instead of its web page content. |
2. Update your cookbook's version metadata
Before you upload an updated cookbook to Chef server, you should always update your cookbook's version metadata to ensure that each version is tied to a specific set of functionality.
Your cookbook's metadata.rb file holds the cookbook's version. When you run the
chef generate cookbook command to create your cookbook, the initial version is set to 0.1.0. Here's what your learn_chef_iis cookbook's metadata.rb file looks like.
Editor: ~/learn-chef/cookbooks/learn_chef_iis/metadata.rb
1
2
3
4
5
6
7
8
9
| name 'learn_chef_iis'
maintainer 'The Authors'
maintainer_email 'you@example.com'
license 'all_rights'
description 'Installs/Configures learn_chef_iis'
long_description 'Installs/Configures learn_chef_iis'
version '0.1.0'
issues_url 'https://github.com/learn-chef/learn_chef_iis/issues' if respond_to?(:issues_url)
source_url 'https://github.com/learn-chef/learn_chef_iis' if respond_to?(:source_url) |
The learn_chef_iis cookbook is currently at version 0.1.0.
Most Chef cookbooks follow the Semantic Versioning scheme. Version numbers are typically written as MAJOR.MINOR.PATCH, where:
- MAJOR specifies a change that's incompatible with previous versions.
- MINOR specifies new functionality that's backwards-compatible with previous versions.
- PATCH specifies backwards-compatible bug fixes.
An update to the HTML template represents a minor change in functionality, so let's increment the middle number, making your cookbook's version 0.2.0.
Modify your copy of metadata.rb like this. The version field changes to '0.2.0'.
Editor: ~/learn-chef/cookbooks/learn_chef_iis/metadata.rb
1
2
3
4
5
6
7
8
9
| name 'learn_chef_iis'
maintainer 'The Authors'
maintainer_email 'you@example.com'
license 'all_rights'
description 'Installs/Configures learn_chef_iis'
long_description 'Installs/Configures learn_chef_iis'
version '0.2.0'
issues_url 'https://github.com/learn-chef/learn_chef_iis/issues' if respond_to?(:issues_url)
source_url 'https://github.com/learn-chef/learn_chef_iis' if respond_to?(:source_url) |
Learn more about cookbook versioning
3. Upload your cookbook to the Chef server
Now you're ready to upload your cookbook to the Chef server. Run the knife cookbook upload command like this.
Terminal: ~/learn-chef
$ | knife cookbook upload learn_chef_iisUploading learn_chef_iis [0.2.0]Uploaded 1 cookbook.
|
4. Run the cookbook on your node
Now that your updated cookbook is on the Chef server, you can run chef-client on your node. The chef-client command pulls from Chef server the latest cookbooks from the node's run-list and applies the run-list to the node.
To run chef-client on your node remotely from your workstation, you could create a WinRM or Remote Desktop connection to your node and then run chef-client. Another way is to use the knife winrm command. A benefit to using the knife winrm command is that it enables you to run chef-client (or any other command) on multiple nodes at the same time.
Recall that the Chef server stores information about your nodes. This information is indexed and is searchable from tools such as knife. When you run knife winrm, you can either specify your node's IP address or a search query that specifies which nodes to connect to. Because the search query syntax supports multiple search patterns and can contain multiple search criteria, you can use knife winrm to run chef-client on multiple nodes at the same time.
Run the following knife winrm command to run your updated cookbook on your node. Replace USER and PASSWORD with your values. Also replace node1-windows with your node's name if you used a different name to bootstrap your node.
- If you're working with a cloud instance
If you're working with an Amazon EC2, Microsoft Azure, or Google Compute Engine instance, replace the ipaddress part of the --attribute ipaddress argument with the corresponding entry from this table.
| Cloud provider | Attribute | Notes |
|---|
| EC2 | cloud.public_hostname | Chef sets this attribute during the bootstrap process. |
| Azure | cloud.public_ip | This is the attribute you set in the previous part when you bootstrapped your node. |
| Compute Engine | cloud_v2.public_ipv4 | Chef sets this attribute during the bootstrap process. |
For example, if you're working with an EC2 instance, you would specify --attribute cloud.public_hostname.
Terminal: ~/learn-chef
$ | knife winrm 'name:node1-windows' chef-client --winrm-user USER --winrm-password 'PASSWORD' --attribute ipaddress
|
Here's an example.
Terminal: ~/learn-chef
$ | knife winrm 'name:node1-windows' chef-client --winrm-user Administrator --winrm-password '7pXySo%!Cz' --attribute ipaddress172.31.62.107 Starting Chef Client, version 13.8.5172.31.62.107 172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: *** Chef 13.8.5 ***172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: *** Chef 13.8.5 ***172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: Platform: x64-mingw32172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: Platform: x64-mingw32172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: Chef-client pid: 480172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: Chef-client pid: 480172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: The plugin path C:\chef\ohai\plugins does not exist. Skipping...172.31.62.107 [2018-05-03T15:34:18+00:00] INFO: The plugin path C:\chef\ohai\plugins does not exist. Skipping...172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Run List is [recipe[learn_chef_iis]]172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Run List is [recipe[learn_chef_iis]]172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Run List expands to [learn_chef_iis]172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Run List expands to [learn_chef_iis]172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Starting Chef Run for node1-windows172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Starting Chef Run for node1-windows172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Running start handlers172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Running start handlers172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Start handlers complete.172.31.62.107 [2018-05-03T15:34:21+00:00] INFO: Start handlers complete.172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Error while reporting run start to Data Collector. URL: https://ec2-34-207-124-26.compute-1.amazonaws.com/organizations/4thcoffee/data-collector Exception: 404 -- 404 "Not Found" (This is normal if you do not have Chef Automate)172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Error while reporting run start to Data Collector. URL: https://ec2-34-207-124-26.compute-1.amazonaws.com/organizations/4thcoffee/data-collector Exception: 404 -- 404 "Not Found" (This is normal if you do not have Chef Automate)172.31.62.107 resolving cookbooks for run list: ["learn_chef_iis"]172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Loading cookbooks [learn_chef_iis@0.2.0]172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Loading cookbooks [learn_chef_iis@0.2.0]172.31.62.107 Synchronizing Cookbooks:172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Storing updated cookbooks/learn_chef_iis/templates/Default.htm.erb in the cache.172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Storing updated cookbooks/learn_chef_iis/templates/Default.htm.erb in the cache.172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Storing updated cookbooks/learn_chef_iis/metadata.rb in the cache.172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Storing updated cookbooks/learn_chef_iis/metadata.rb in the cache.172.31.62.107 - learn_chef_iis (0.2.0)172.31.62.107 Installing Cookbook Gems:172.31.62.107 Compiling Cookbooks...172.31.62.107 Converging 3 resources172.31.62.107 172.31.62.107 Recipe: learn_chef_iis::default172.31.62.107 * powershell_script[Install IIS] action run[2018-05-03T15:34:22+00:00] INFO: Processing powershell_script[Install IIS] action run (learn_chef_iis::default line 6)172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Processing powershell_script[Install IIS] action run (learn_chef_iis::default line 6)172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Processing powershell_script[Guard resource] action run (dynamically defined)172.31.62.107 [2018-05-03T15:34:22+00:00] INFO: Processing powershell_script[Guard resource] action run (dynamically defined)172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: powershell_script[Guard resource] ran successfully172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: powershell_script[Guard resource] ran successfully172.31.62.107 (skipped due to not_if)172.31.62.107 * windows_service[w3svc] action enable[2018-05-03T15:34:23+00:00] INFO: Processing windows_service[w3svc] action enable (learn_chef_iis::default line 12)172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Processing windows_service[w3svc] action enable (learn_chef_iis::default line 12)172.31.62.107 (up to date)172.31.62.107 * windows_service[w3svc] action start[2018-05-03T15:34:23+00:00] INFO: Processing windows_service[w3svc] action start (learn_chef_iis::default line 12)172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Processing windows_service[w3svc] action start (learn_chef_iis::default line 12)172.31.62.107 (up to date)172.31.62.107 * template[c:\inetpub\wwwroot\Default.htm] action create[2018-05-03T15:34:23+00:00] INFO: Processing template[c:\inetpub\wwwroot\Default.htm] action create (learn_chef_iis::default line 16)172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Processing template[c:\inetpub\wwwroot\Default.htm] action create (learn_chef_iis::default line 16)172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: template[c:\inetpub\wwwroot\Default.htm] backed up to c:/chef/backup\inetpub\wwwroot\Default.htm.chef-20180503153423.306083172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: template[c:\inetpub\wwwroot\Default.htm] backed up to c:/chef/backup\inetpub\wwwroot\Default.htm.chef-20180503153423.306083172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: template[c:\inetpub\wwwroot\Default.htm] updated file contents c:\inetpub\wwwroot\Default.htm172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: template[c:\inetpub\wwwroot\Default.htm] updated file contents c:\inetpub\wwwroot\Default.htm172.31.62.107 172.31.62.107 - update content in file c:\inetpub\wwwroot\Default.htm from a7298b to e0feed172.31.62.107 --- c:\inetpub\wwwroot\Default.htm 2018-05-03 15:34:04.000000000 +0000172.31.62.107 +++ c:\inetpub\wwwroot/chef-Default20180503-480-r0m7zy.htm 2018-05-03 15:34:23.000000000 +0000172.31.62.107 @@ -1,6 +1,6 @@172.31.62.107 <html>172.31.62.107 <body>172.31.62.107 - <h1>hello world</h1>172.31.62.107 + <h1>hello from WIN-OPJ5HH81G1B.ec2.internal</h1>172.31.62.107 </body>172.31.62.107 </html>172.31.62.107 172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Chef Run complete in 1.437499 seconds172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Chef Run complete in 1.437499 seconds172.31.62.107 172.31.62.107 Running handlers:172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Running report handlers172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Running report handlers172.31.62.107 Running handlers complete172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Report handlers complete172.31.62.107 [2018-05-03T15:34:23+00:00] INFO: Report handlers complete172.31.62.107 Chef Client finished, 1/4 resources updated in 05 seconds
|
Here you see that your node downloads and applies version 0.2.0 of the learn_chef_iis cookbook.
The 'name:node1-windows' part is the search query. It returns all nodes that have the name "node1-windows". In practice, you would have only one node with a given name. Recall that a search query supports multiple patterns. If you were to specify 'name:node1-*', which uses a wildcard pattern, knife winrm would run chef-client on all nodes whose name begins with "node1-".
The --attribute part tells knife which node attribute to use when opening a WinRM connection. The default is to use the node's FQDN. For learning purposes, here we specify ipaddress to use the node's IP address because your node may not have a resolvable FQDN. In practice, you might omit this argument if your node does have a resolvable FQDN.
| Remember, in practice it's common to configure Chef to act as a service that runs periodically or as part of a continuous integration or continuous delivery (CI/CD) pipeline. For now, we're updating our server configuration by running chef-client manually. |
5. Verify the result
As before, run curl to verify the configuration. Replace the IP address you see here with yours. You'll see that the "hello world" message is replaced with your node's FQDN.
Terminal: ~/learn-chef
$ | curl 52.91.187.161<html> <body> <h1>hello from WIN-OPJ5HH81G1B.ec2.internal</h1> </body></html>
|
You can also open a web browser from your workstation and navigate to your web server. Here's an example for a system whose FQDN is "node1-windows".

To summarize, to update your cookbook you used a template. A template enables you to write a single, general recipe that’s customized for a particular node as the recipe runs. That means you don’t have to write a custom version of your recipe for every node.
You also ran knife winrm to update your node. knife winrm invokes the command you specify over a WinRM connection on a node – in our case chef-client. You didn't have to specify the run-list because you already set that up when you bootstrapped the node.