diff --git a/README.md b/README.md index 041d7fb..661bbbb 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,30 @@ Or install it yourself as: Detailed documentation of the helper methods can be seen at http://rdoc.info/github/3ofcoins/chef-helpers/ +### JSONPath access to attributes + +The `Chef::Node` class is monkey-patched to allow easy deep access to +the attributes using the +[JSONPath](http://goessner.net/articles/JsonPath/) syntax: + +``` +chef > require 'chef-helpers' + => true +chef > node['$..name'] + => ["portinari-2.local", "Java(TM) SE Runtime Environment", "Java HotSpot(TM) 64-Bit Server VM", "Darwin"] +chef > node['$.kernel.name'] + => ["Darwin"] +``` + +Regular access to attributes is preserved; JSONPath is used only when +the attribute name starts with `$` character, or if a `JSONPath` +instance is used for indexing. + +The [jsonpath gem](https://github.com/joshbuddy/jsonpath) is used for +the implementation. While the original gem allows modification, it's +not straightforward to achieve with Chef's attributes, so only reading +attributes with JSONPath is supported. + ## Contributing 1. Fork it diff --git a/chef-helpers.gemspec b/chef-helpers.gemspec index 77ae5af..6ef1052 100644 --- a/chef-helpers.gemspec +++ b/chef-helpers.gemspec @@ -16,4 +16,5 @@ Gem::Specification.new do |gem| gem.version = ChefHelpers::VERSION gem.add_dependency "chef" + gem.add_dependency "jsonpath" end diff --git a/lib/chef-helpers/node.rb b/lib/chef-helpers/node.rb index 44dae1f..01cb3be 100644 --- a/lib/chef-helpers/node.rb +++ b/lib/chef-helpers/node.rb @@ -1,4 +1,5 @@ require 'chef/node' +require 'jsonpath' class Chef::Node @@ -7,14 +8,14 @@ class Chef::Node # attribute. The `allies` attribute - if set - should be an array of # node names or node search queries; the named nodes and search # results will be added to node's allies. - # + # # This is mostly useful when defining firewall or other access # rules, to easily limit access to insides of a cluster plus a # handful of friendly machines. # # @return [Array] Array of node's "allies". def allies - @allies ||= + @allies ||= begin rv = [] q = Chef::Search::Query.new @@ -30,12 +31,12 @@ def allies end # Find out, which IP should be used to contact with other node. - # + # # If both nodes are on EC2 and in the same region, then other node's # `ec2.local_ipv4` attribute is used. Otherwise, if other node is a # cloud instance, its `cloud_public.ipv4` attribute is # used. Otherwise, other node's `ipaddress` is used. - # + # # @note This method may return wrong IP with non-EC2 cloud # providers, and can use some tweaking for such cases. # @param [Chef::Node] other_node Node, whose IP we need to know @@ -51,4 +52,15 @@ def ip_for(other_node) other_node['ipaddress'] end end + + # jsonpath access to node attributes + def brackets_with_jsonpath(key) + case key + when JsonPath then key.on(self.to_hash) + when /^\$/ then JsonPath.on(self.to_hash, key) + else self.brackets_without_jsonpath(key) + end + end + alias_method :brackets_without_jsonpath, :[] + alias_method :[], :brackets_with_jsonpath end diff --git a/lib/chef-helpers/version.rb b/lib/chef-helpers/version.rb index 8dc0862..a557e60 100644 --- a/lib/chef-helpers/version.rb +++ b/lib/chef-helpers/version.rb @@ -1,3 +1,3 @@ module ChefHelpers - VERSION = "0.0.6" + VERSION = "0.0.7" end