Chef search provides the ability to query data indexed on Chef Server. The search query runs on Chef Server and search results are returned to clients. Queries can be invoked by using
knife
on the command line or from within a recipe. Typical queries are usually inventory related, such as a count and system names of all the computers that have particular operating system configurations or software installed. For example, searches for versions of the openssl library vulnerable to the Heartbleed Virus were quite popular as we were writing this book.Search from the Command Line
Let’s start by performing a search query with
knife
on the command line. Use the chef-playground directory you created in Chapter 11. Use the same dual command prompt setup you used there. Start the chef-zero
server on an open port in one window. We will be using port 9501 in the examples in this chapter:
Then, in the other window, make the chef-playground directory the current working directory and run the
knife upload nodes
command to populate Chef Server with some test data about nodes:Search from the Command Line with Knife
You can also perform searches in production on the command line with the
knife search
command. The search query syntax with knife
is in the following form:
The index can be one of the following:
node
client
environment
role
- <name of data bag>
In this chapter, we’ll use
node
for the index field. Figure 12-1 shows an example of a search for nodes that have an IP address beginning with 10.1.1.
Chef uses Apache Solr for searching and search indexing. The following command performs a search query for all nodes and returns the results using the Solr search query string
"*:*
.” The results contain the test data we just populated with knife upload
, showing three nodes registered to be managed by Chef.
Chef search queries use the Solr “<attribute>:<search_pattern>” form:
Use an asterisk (“*”) within a search query to perform a wildcard search matching 0 or more characters:
Use a question mark (“?”) to match any single character:
You can add specific key-value pairs in the query part of the
knife search
command line. The following query will return the item where node == snowman
:NOTE
To obtain a list of attribute names to use in a search, run the
knife <index> show
command using the --long
option. It will show you all the available attributes. For example, we ran the following command to determine that the attribute for Node Name:
was hostname
:
Note that our test data doesn’t include all the possible attributes. You’ll need to run
knife node show
against a real Chef Server setup. Another way to collect this information for a node without needing a real setup is to run ohai
and look through the results. Most of the attributes about a node come from ohai
.Search in a Recipe Using Test Kitchen
You can also perform search queries in your Chef code. In this section we’ll write a cookbook using Test Kitchen and
chef_zero
that performs search queries. Create the directory chef-playground/cookbooks, and make sure it is the current working directory:
Linux/Mac OS X:
Windows:
Now, generate a
nodes
cookbook in the chef-playground/cookbooks directory.
Chef Development Kit:
Chef Client:
Edit the .kitchen.yml to make sure you are using the
chef_zero
provisioner and our favorite basebox image as shown in Example 12-1. Notice there is a new addition to the provisioner:
stanza, the nodes_path:
nodes_path
is a relative path pointing to the chef-playground/nodes directory we created with our test data in Chapter 11. Test data is normally located somewhere outside the main cookbook source code so it doesn’t get inadvertently uploaded to the Chef server.
Let’s write a recipe that performs a search query on Chef Server for all nodes, like we did in the previous section.Chef provides a
search()
method that you can use in your Chef code. It takes two parameters, similar to the two command line
parameters used in knife search
:search(
index
,
search_query
)
:- index
- Possible values for index are
node
,client
,environment
,role
, and <name of data bag>. In this example, we’ll be usingnode
. - search_query
- Apache Solr search query.
Make sure recipes/default.rb matches the code contained in Example 12-2. It contains Chef code that queries Chef Server for all items in the
users
data bag.
The
.each
statement in recipes/default.rb is a looping construct specific to Ruby. If you are familiar with other programming languages, look at the following code for something that might be a little more familiar. The following code creates a counter
variable, incrementing it by 1 until it equals 5:
Although the preceding is completely valid Ruby, a more idiomatic way is to use the
.each
iterator to return all the elements in an array one-by-one. Ruby shines in having really compact ways to specify common coding constructs.
The
do..end
block construct is more sophisticated than we’ve covered so far. It can be used to define a method with no name. Also, you can pass this nameless method one or more parameters enclosed by two vertical bars (||), such as |counter|
in the following example.
In the following example, we pass a code block to
(0..5).each
. When you pass a code block to an iterator method, it will execute the specified method for each item. In this case, each item of the range (0..5)
will be passed to our code block as the |counter|
variable. The block uses this variable to print out each value in the range:
We’re doing something similar in Example 12-2, iterating through each node item returned by
search()
and returning the item content in the matching_node
variable. matching_node
is a hash containing the key-value pairs in the node item.
The code just reads these values from the
matching_node
hash and uses the to_s
method to print a string representation of the object using log
, which is the node name.
Run
kitchen converge
. If all goes well, you should notice that Test Kitchen uploads the cookbook code to the sandbox environment and creates node entries in a chef-zero
instance. Then it runs the cookbook code, which performs a query for all nodes, printing out the following results:NOTE
Sharp-eyed readers might notice that the search returns four results instead of the three we received running
knife
using the command line. The search result returns the nodes atwood
, snowman
, susu
, and default-centos65
. The additional node entry is the sandbox node Test Kitchen creates for us. When Test Kitchen performs a kitchen converge
, it automatically registers the sandbox instance as a node with its own chef-zero
instance.
You have been introduced to Chef search. We’re done with the
chef-zero
instance on your host and the Test Kitchen sandbox environment. Hit Ctrl-C in the window in which you launched chef-zero
to stop the Chef Zero server. Make sure the chef-playground/cookbooks/nodes directory with your cookbook is the current working directory, then run:Summary
In this chapter we introduced you to Chef search. Chef Server uses Apache Solr behind the scenes to add support for searching and indexing. The Apache Solr
"<attribute>:<query>"
syntax is also used for search queries. You can search from anything that can talk with Chef Server, given that Chef Server’s search capability is implemented as an API. We showed you how to search from the command line using knife node search
and how to search within a recipe using the search()
method.
In the next chapter, we’ll cover data bags. Data bags contain data that can be accessed by more than one node. Data bags were added as a feature in Chef Server to get around the limitation that node attributes can be read only by the node that created the data, not by any other node.
No comments:
Post a Comment