Debugging Chef Recipes on AWS OpsWorks – Access Custom JSON and Data Bag Attributes

amazon-web-serviceschefopsworks

I'd like to use a chef-shell session on an aws opsworks ec2 server so I can test some environment and instance specific code I'd like to include in a custom recipe. For example, I'd like to see the output of instance attributes such as node[:opsworks][:instance][:layers] or node[:opsworks][:instance][:public_dns_name] as well as data I have passed to the opsworks stack using custom json.

I can start chef-shell, I just don't know how to use it to access opsworks attributes.

If I ssh into the opsworks ec2 instance I can access attributes like node['ec2']['instance_id'] but no opsworks specific ones like node['opsworks']['instance']['layers']

root@mongodb1:/opt/aws/opsworks/current/bin# ./chef-shell
loading configuration: none (standalone session)
Session type: standalone
Loading......done.

This is the chef-shell.
 Chef Version: 11.10.4
 http://www.opscode.com/chef
 http://docs.opscode.com/

run `help' for help, `exit' or ^D to quit.

Ohai2u ubuntu@mongodb1.localdomain!
chef > attributes_mode
chef:attributes > node['ec2']['instance_id']
 => "i-c1a98f2c"
chef:attributes > node['opsworks']['instance']['layers']
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb#1):4
chef:attributes >

Best Answer

The Custom JSON and the Stack's state are pushed to the instance in a JSON struct when an OpsWorks event (setup, configure, deploy, undeploy, shutdown) occurs. If you want your recipe to see the up-to-the-minute state of the OpsWorks Stack then you need to run your recipe from the OpsWorks UI via the Deploy -> Run Command -> Execute Recipes form.

The JSON sent by OpsWorks is stored on the instance. If you're willing to use potentially-stale Stack state info which is only as fresh as the last time this instance ran an OpsWorks event, you can look for the most recent *.json file on the instance in /var/lib/aws/opsworks/chef, and parse it via Ruby code.

You can also use the opsworks-agent-cli utility on the instance to (re-)run the recipes from an OpsWorks event directly from the command-line on the instance. This utility will re-run OpsWorks events - it won't initiate new events, and it does not pull in a fresh copy of the stack state or the Custom JSON, rather it reuses the .json file that OpsWorks sent to the instance when that event was run originally. For example, in order to rerun the setup event on your instance (because the setup event was definitely run already):

sudo opsworks-agent-cli run_command setup

In order to rerun the same set of recipes you executed last time you ran Execute Recipes from the UI:

sudo opsworks-agent-cli run_command execute_recipes

This kind of sucks, because you need to run the event via the UI first. So if you want to run a custom recipe, or if you want to update custom cookbooks, you first need to run that event from the UI. But, the second, third, and subsequent times you can rerun those events via opsworks-agent-cli.

See here for more about the opsworks-agent-cli.