Y’all, I was in InSpec heaven a couple of weeks ago. I was on a project where I was supposed to create an InSpec profile that tests the build and application configuration of a set of servers within a pipeline in TeamCity - smoke-tests. I had to translate a bunch of ServerSpec into InSpec and run the InSpec profile independently of the cookbook. Seems easy enough, but the challenge is testing all the different environments and using different tests for each node spun up. The client also wanted it to be in one step for all the nodes, not a different step for each one.
But first, if you’ve missed out on any of my tutorials, you can find them here:
- Day 1: Hello World
- Day 2: Command Resource
- Day 3: File Resource
- Day 4: Custom Matchers
- Day 5: Creating a Profile
- Day 6: Ways to Run It and Places to Store It
- Day 7: How to Inherit a Profile from Chef Compliance Server
- Day 8: Regular Expressions
If you’d like to follow along, then you’re welcome to go clone this practice InSpec profile.
Here’s what we’ll cover
- Assessing our needs
- Declaring the Attributes
- Use the attributes in an if statement
- Create different attributes yamls to run the different tests
- Concluding Thoughts
Assessing our needs
So let’s say that you have two different roles that you want to test: database and webserver. And let’s keep it simple and just test one environment where you spin up one machine for each role.
That means that we’re going to need two different sets of tests:
- One for client tests
- One for server tests
If you’re following along in the practice InSpec profile, then you’ll see that there are three different sets of tests (well, really just one test in each control, but you get the picture.) We’re going to set it up so that we can run one test for each role.
Now, the big bummer of this is that attributes don’t work for InSpec in Test Kitchen just yet like they do for recipes, but I think that would be great if they did! (hint hint) Maybe sometime soon we’ll get that.
Declaring the Attributes
Let’s go over to our control and add the attributes hard-coded with a default value and see what it does. We’re going to
declare the attributes above where we’re using them. So add this above your client
control.
role = attribute('role', default: 'base', description: 'type of node that the InSpec profile is testing')
Use the attributes in an if statement
Now that the attributes are declared, we’ll need to wrap our controls in an if
statement so that it only tests that
block when we want it to. Your client
control block is going to end up looking like this:
if ['client', 'base'].include? role
control "Testing only client" do
title "Tests for client"
desc "The following tests within this control will be used for client nodes."
describe user('client') do
it { should exist }
end
end
end
You’re saying, If the node you’re looking at is a client or base, then run this control block. You’ll do the same for
the server
control:
if ['server', 'base'].include? role
control "Testing only server" do
title "Tests for Server"
desc "The following tests within this control will be used for server nodes."
describe user('server') do
it { should exist }
end
end
end
What happens when you run it now? Well, nothing different yet, so let’s make that happen.
Create different attributes yamls to run the different tests
We’ll need to add a few attributes files to our profile to call on to change those roles. These are going to be yaml files, and while you may put them anywhere you want, I think it’s nice if they get their own directory inside the profile. Go ahead and create these now.
In each yaml, put the respective attribute values.
# In attributes.yml
role: base
# In client-attributes.yml
role: client
# In server-attributes.yml
role: server
We’re going to run these tests on our local machine, and while we know, obviously, that these tests will fail, we’re going to see how the attributes ran the different tests.
So then, let’s watch it run just the tests for only base and client by running:
inspec exec . --attrs attributes/client-attributes.yml
See how it didn’t include the server only tests?
And now let’s watch it run the tests for just base and server roles:
inspec exec . --attrs attributes/server-attributes.yml
See how it didn’t include the tests for client only?
And there you go! That’s a simple guide to attributes!
Concluding Thoughts
I love this feature. It gives a lot of flexibility and control, and you can use it in a lot of different ways. The trick is to hard-code the attributes first to make sure it’s working.
So just a little job update—I’m loving it over here at 10th Magnitude. I’m learning so much. Sure, I ask some dumb questions from time to time, and I feel really dumb about them later, but I am in the perfect position to learn a ton. _Feeling grateful.
Go to Day 10: Attributes with Environment Variables