howdy all.
I want to make assertions on files that I can’t create a list for a-priori. I need to do something like
get_list_of_files_in_dir.each do |f|
describe file(f) it { should exist }
end
I wanted to use Dir.glob
for this, but that is executed on the local machine, not the target.
Is there a way for What is considered good practice for getting the list of files in a directory on the target machine?
Thanks!
AFAIK currently you have to use the command
resource. I'm not aware of the inspec resource classes exposing something to list the files in a directory. Thankfully the command
resource is your Swiss army knife when inspec doesn't support something.
This is noted in the following GitHub issue: add directories resource · Issue #709 · inspec/inspec · GitHub
An example of the workaround is provided:
command('find /lib -type f').stdout.split.each do |fname|
describe file(fname) do
its('owner') { should cmp 'root' }
end
end
I also provide an example of how to scrape command
output and how to package this into a custom resource, in my Learning Chef
video on Safari if you have a subscription:
The example code is here: learningchef-video/chefdk_version.rb at master · learningchef/learningchef-video · GitHub
class ChefdkVersion < Inspec.resource(1)
name 'chefdk_version'
def initialize
chef_version_output = inspec.command('/opt/chefdk/bin/chef --version').stdout
version = chef_version_output.match(/Chef Development Kit Version: (\d+\.\d+\.\d+)/)[1]
@major_version = version.split('.')[0]
@minor_version = version.split('.')[1]
@patch_version = version.split('.')[2]
end
def major_version
@major_version.to_i
end
def minor_version
@minor_version.to_i
end
def patch_version
@patch_version.to_i
end
end
There's mention of providing more proper support for dynamic file listings in the GitHub issue as well, but I don't think it has made it into the product yet.
P.S. By creating a custom resource, you could create your own version of a Dir
resource that lists files in a directory on the remote machine (until Chef provides equivalent functionality in a prepackaged resource).
I would say that encapsulating the “remote directory listing” in a custom resource would be a recommended best practice for adding this new capability.
1 Like
Thanks @misheska that’s exactly what I ended up doing (going the command().stdout.split
route. Great to know that this is considered the “right” way of doing things - it felt a bit dirty.
Is the “solution” plugin enabled on this discourse ? I’d like to have one of the moderators set this as a solutin
You’re welcome. If it helps, a great deal of inspec itself is basically a bunch of command
parsing, so it should definitely feel “right”.
Take a look at the source for the inspec resources sometime. You’ll see a lot of it: https://github.com/inspec/inspec/tree/master/lib/resources
If you search for "inspec.command"
, you’ll get a lot of hits.
How does inspec get a list of running services? Like so:
inspec.command('find /etc/rc*.d /etc/init.d/rc*.d -name "S*"').stdout
List of yum repos:
inspec.command('yum -v repolist all')
List of docker images:
inspec.command('docker images -a --no-trunc --format \'{ "id": {{json .ID}}, "repository": {{json .Repository}}, "tag": {{json .Tag}}, "size": {{json .Size}}, "digest": {{json .Digest}}, "createdat": {{json .CreatedAt}}, "createdsize": {{json .CreatedSince}} }\'').stdout
And so on. A lot of inspec itself is just encapsulating robust command scraping.
1 Like