could not find filename for attribute .DS_Store in cookbook

The Macintosh workstation saves application states in .DS_Store files. When you edit your Chef cookbooks the MacOS leaves these files in many folders.

When the Chef cookbook is executed, the Chef Client reads all files in the attributes folder and tries to extract values from them. If the .DS_Store file is uploaded with the rest of the cookbook to the Chef server, the Chef cookbook execution stops with the error message:

Recipe Compile Error in /var/chef/cache/cookbooks/…/attributes/.DS_Store

could not find filename for attribute .DS_Store in cookbook …

When you test your cookbook with Test Kitchen, there is no error, so you cannot detect the existence of the file until the Chef cookbook starts to run on the instance.

Even though the.DS_Store file cannot be seen in Finder, it still can be there. It is a hidden file, and even if you enable the display of hidden files, Finder does not show it.

$ cd attributes
$ ls -a
. .. .DS_Store default.rb

To remove the .DS_Store file from the cookbook

  1. Make sure the .DS_Store file is added to the chefignore file
  2. Delete the file from the folder on your workstation
    rm .DS_Store
  3. Increment the version of the cookbook in the metadata.rb file
  4. Upload the new version of the cookbook to the Chef server
    knife cookbook upload MY_COOKBOOK --freeze


Skip steps in an InSpec integration test based on Chef attribute values

To speed up the test of some complex recipes, I use an attribute to skip certain long-running installations when I only need to test the rest of the recipe.

We will pass Chef Attribute values into an InSpec test using environment variables.

Declare an attribute in the atrributes.rb file with a safe default value, to allow the execution of all steps if the value is not overridden

# Set this to true in the .kitchen.yml file to skip long-running tasks during local test
default['quick_launch_for_test'] = false

Set the value in the suites: section of the kitchen.yml file to true to skip the long-running installations

    quick_launch_for_test: true

Save the attribute value in an environment variable in the recipe to pass it to InSpec

# Store the value in an environment variable for the integration test
env 'quick_launch_for_test' do
  value "#{node['quick_launch_for_test']}"

Make a decision in the recipe based on the value of the attribute

if ( node['quick_launch_for_test'] != true )
  #Microsoft Visual Studio Community 2017 #

Read the value of the environment variable into a local variable in the InSpec test file. If the environment variable does not exist, or the value is not “true”, the value of the local_execution variable will be “false”.

local_execution = ( os_env('quick_launch_for_test').content() == 'true')

Use the if statement to make the decision in your InSpec test file

if !local_execution
  describe package('Microsoft Visual Studio Community 2017') do
    it { should be_installed }


Chef NoMethodError, undefined method

When you try to bootstrap a node to a Chef server, you may get the error message

Compiling Cookbooks…
Recipe Compile Error in c:/chef/cache/cookbooks/…/attributes/default.rb
undefined method `…=’ for #<Chef::Node::VividMash:0x0000000004ca3268>

Relevant File Content:
>> default. …

In my case, the cookbook compiler could not interpret the dot notation in the recipes.

There are multiple ways to declare and use the Chef attributes:





The last format, the dot notation is a legal form, but not accepted by the compiler that checks the cookbooks during bootstrapping. The same cookbook works perfectly in Test Kitchen, and in chef-client.

The solution is to change the dot notation to one of the other formats, preferably to the first in the list above.


Switching to a new Chef server

The administrator of the Chef organization

Download the validation key

Do this only once for the organization.

This step resets the validation key, so the existing server images will not be able to connect to the Chef organization.

  1. On the Administration tab on the left select Organizations > Reset validation Key
  2. Click the Reset Key button,
  3. This is the only time you are able to download the validator key. Click the Download button to save it on your workstation.

Every user

Download your personal key from the server and configure knife. See DevOps Engineering part 4. – Connect to the Chef server

Upload all cookbooks to the new Chef server

  1. Copy all cookbooks to the new chef directory
  2. Open a terminal in the cookbooks directory and start to upload all cookbooks
    knife cookbook upload --all --freeze --force
  3. When you get the message

    ERROR: Cookbook XXX depends on cookbooks which are not currently
    ERROR: being uploaded and cannot be found on the server.
    ERROR: The missing cookbook(s) are: ‘YYY’ version ‘>= 0.0.0’, ‘ZZZ’ version ‘>= 0.0.0’

    1. Change to that XXX cookbook directory and execute
      berks upload
  4. Repeat step 3 until all cookbooks have successfully uploaded to the server.

Upload the environment files

  1. Open a terminal in the environments directory.
knife environment from file qa.json uat.json prod.json

Upload the data bags

  1. Open a terminal window in the data-bags directory and upload the data bags.
knife data bag create MY_DATA_BAG
knife data bag from file MY_DATA_BAG MY_DATA_BAG/MY_ITEM1.json
knife data bag from file MY_DATA_BAG MY_DATA_BAG/MY_ITEM2.json
knife data bag from file MY_DATA_BAG MY_DATA_BAG/MY_ITEM3.json



Waiting for SSH service on …:22, retrying in 3 seconds

When you try to launch a new EC2 instance in AWS using Chef Test Kitchen and the process times out with the message:

  Waiting for SSH service on …:22, retrying in 3 seconds

$$$$$$ [SSH] connection failed, terminating (#<Net::SSH::AuthenticationFailed: Authentication failed for user …@…>)
>>>>>> ——Exception——-
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>> Failed to complete #create action: [SSH session could not be established] on default-rhel7
>>>>>> ———————-
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose –all` for configuration

Check the access to the “ssh_key” which is specified in the platforms: driver: transport: section of the .kitchen.yml file.

The .pem file should be accessible from the cookbook directory with the absolute or relative path.

Failed to complete #create action: [undefined method `version’ for nil:NilClass] on default…

When you execute kitchen converge to launch an EC2 instance in AWS with Chef Test Kitchen, you get the error message:

>>>>> ——Exception——-
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>> Failed to complete #create action: [undefined method `version’ for nil:NilClass] on default-windows-2012r2
>>>>>> ———————-
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose –all` for configuration

The kitchen-ec2 driver tries to read the operating system version from the name of the image, but it cannot find it.

When you create your own AMI (Amazon Machine Image), make sure the version of the operating system is in the name:


An acceptable name is my_windows-2012r2_base-1

Could not load the ‘vagrant’ driver from the load path

When you execute the kitchen converge command to launch a virtual machine on your workstation with the Vagrant driver, you may get the error message:

>>>>> ——Exception——-
>>>>>> Class: Kitchen::ClientError
>>>>>> Message: Could not load the ‘vagrant’ driver from the load path. Please ensure that your driver is installed as a gem or included in your Gemfile if using Bundler.
>>>>>> ———————-
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose –all` for configuration

An additional Ruby installation on your workstation besides the version came with the Chef Development kit can cause this.

To force Test Kitchen to use the Ruby instance that was installed with the Chef Development kit start your commands with chef exec:

 chef exec kitchen list

To check the Ruby installations on your workstation, execute

which ruby

The path should be


If the result is something else, uninstall the extra Ruby version.

If you use the Ruby Version Manager (RVM), uninstall the current ruby version, then uninstall RVM. See

Reinstall the Chef Development Kit, which will install the recommended Ruby version on your workstation.

If you get the Vagrant error message:

Vagrant failed to initialize at a very early stage …


follow the recommended steps on the screen to reinstall the Vagrant plugins.

Vagrant installation

 Vagrant Installation

  • Download Vagrant from and follow the instructions to install it.
  • Select DOWNLOAD…
  • Select the operating system of your workstation. For
    • Ubuntu: Debian
    • RedHat: Centos

Keep multiple versions on your workstation

Vagrant has an installer, that places the bin and embedded folders to “/opt/vagrant”. To be able to keep multiple versions of Vagrant execute the following:

cd /opt/vagrant
mkdir vagrant_MY_VERSION                                 # Create a folder for the new version
sudo chown -R YOUR_USER_NAME:wheel bin                   # Set the owner, so you can move it
sudo chown -R YOUR_USER_NAME:wheel embedded              # Set the owner, so you can move it
mv bin vagrant_MY_VERSION                                # Move the folder to the version specific location
mv embedded vagrant_MY_VERSION                           # Move the folder to the version specific location
rm vagrant                                               # Delete the old version of the symbolic link
ln -s /opt/vagrant/vagrant_MY_VERSION/bin/vagrant vagrant # Create the symbolic link


The default credentials of a Vagrant machine are:

  • UserName: vagrant
  • Password: vagrant

Windows in Vagrant

To test your cookbook on a Windows virtual machine locally, create one for Vagrant. See Launch Windows instances locally with Chef Test Kitchen for the details.

Create the AWS credentials file from a Chef Data Bag

When a process on a server instance needs access to an AWS account, the user who will execute the AWS CLI commands needs to be able to automatically authenticate in AWS.

For automatic AWS authentication, the AWS CLI creates two files in the .aws directory:

  • config and
  • credentials.

The location of this directory depends on the operating system and the type of user.

  • On Linux, the location is ~/.aws ( the user’s home directory )
  • On Windows, it is located at C:\Users\USER_NAME\.aws
  • On Windows, if the file was created by SYSTEM, the location is C:\Windows\System32\config\systemprofile\.aws

Store the AWS key values

To create these files, you need to store the AWS Access Key and Secret Key. The safest place for these values is an encrypted data bag. To automatically generate the AWS files, create a data bag file and name it the same as the “id” in the following structure:

  "MY_PROFiLE_1": {
    "region": "MY_REGION_1",
    "aws_access_key_id": "MY_ACCESSKEY_1",
    "aws_secret_access_key": "MY_SECRET_KEY_1"
  "MY_PROFiLE_2": {
    "region": "MY_REGION_2",
    "aws_access_key_id": "MY_ACCESSKEY_2",
    "aws_secret_access_key": "MY_SECRET_KEY_2"

To create and encrypt the data bag see my post on Chef Data Bags

Create the AWS authentication files

  1. In your Chef recipe, first install the AWS CLI and reboot the server, so the new path entry will be available for the Chef process.
  2. The following Chef code will create the AWS config and credential files. The script
    1. opens and decrypts the data bag,
    2. loads it into a hash table,
    3. iterates through the hash items,
    4. skips the “id” item,
    5. stores the AWS key values in a temporary file,
    6. executes the “aws configure” command to generate the AWS config and credential files.
  # Iterate through the data bag and create the credentials file

  puts "***** Creating the AWS credentials file"

  # Load the encrypted data bag into a hash
  aws_credentials = Chef::EncryptedDataBagItem.load('MY_DATA_BAG_NAME', 'MY_DATA_BAG_ITEM_NAME').to_hash

  # Iterate through the items, skip the "id"
  aws_credentials.each_pair do |key, value|

    # skip the "id"
    next if key == "id"

    # Add the credentials to the .aws/credentials file
    puts "Account #{key}, Region #{value['region']}"

    batch "add_aws_credentials_#{key}" do
      code <<-EOF echo #{value["aws_access_key_id"]}> input.txt
        echo #{value["aws_secret_access_key"]}>> input.txt
        echo #{value["region"]}>> input.txt
        echo.>> input.txt
        aws configure --profile #{key} < input.txt



Dynamically set Chef resource attributes

When you need to set a Chef resource attribute based on the current state of the environment, there is a way to dynamically provide the value.

  1. Set the value of a boolean variable with a test,
  2. Declare the Chef resource and assign a reference to it to a variable,
  3. Set the resource attribute based on the value of the boolean variable.
# Set a boolean variable with a test 
  "#{node['domain']}" != ""

# Execute a resource and get a reference to it into a variable
# Set the attribute value based on the boolean variable