summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-06-02 17:12:38 -0500
committerJames Turnbull <james@lovedthanlost.net>2009-06-06 19:57:58 +1000
commitc0bd0aa1a5aaed94dfab25f390199a722d0d5c0d (patch)
treef337015acb2e729ae8ef687dfe077a45390dd01b
parentc16fd1bff64fd426d36e07648a7f8550563ae6e1 (diff)
downloadpuppet-c0bd0aa1a5aaed94dfab25f390199a722d0d5c0d.tar.gz
puppet-c0bd0aa1a5aaed94dfab25f390199a722d0d5c0d.tar.xz
puppet-c0bd0aa1a5aaed94dfab25f390199a722d0d5c0d.zip
Providing JSON support to the Resource class
Signed-off-by: Luke Kanies <luke@madstop.com>
-rw-r--r--lib/puppet/resource.rb72
-rwxr-xr-xspec/unit/resource.rb152
2 files changed, 221 insertions, 3 deletions
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb
index b4458e638..862aadf99 100644
--- a/lib/puppet/resource.rb
+++ b/lib/puppet/resource.rb
@@ -1,15 +1,84 @@
require 'puppet'
require 'puppet/util/tagging'
require 'puppet/resource/reference'
+require 'puppet/util/json'
# The simplest resource class. Eventually it will function as the
# base class for all resource-like behaviour.
class Puppet::Resource
include Puppet::Util::Tagging
+ extend Puppet::Util::Json
include Enumerable
attr_accessor :file, :line, :catalog, :exported
attr_writer :type, :title
+ ATTRIBUTES = [:file, :line, :exported]
+
+ def self.from_json(json)
+ raise ArgumentError, "No resource type provided in json data" unless type = json['type']
+ raise ArgumentError, "No resource title provided in json data" unless title = json['title']
+
+ resource = new(type, title)
+
+ if params = json['parameters']
+ params.each { |param, value| resource[param] = value }
+ end
+
+ if tags = json['tags']
+ tags.each { |tag| resource.tag(tag) }
+ end
+
+ ATTRIBUTES.each do |a|
+ if value = json[a.to_s]
+ resource.send(a.to_s + "=", value)
+ end
+ end
+
+ resource.exported ||= false
+
+ resource
+ end
+
+ def to_json(*args)
+ raise "Cannot convert to JSON unless the 'json' library is installed" unless Puppet.features.json?
+
+ data = ([:type, :title, :tags] + ATTRIBUTES).inject({}) do |hash, param|
+ next hash unless value = self.send(param)
+ hash[param.to_s] = value
+ hash
+ end
+
+ data["exported"] ||= false
+
+ params = self.to_hash.inject({}) do |hash, ary|
+ param, value = ary
+
+ # Don't duplicate the title as the namevar
+ next hash if param == namevar and value == title
+ value = [value] unless value.is_a?(Array)
+ hash[param] = value
+ hash
+ end
+
+ unless params.empty?
+ data["parameters"] = params
+ end
+
+ res = {
+ 'json_class' => self.class.name,
+ 'data' => data
+ }
+ #data.each do |key, value|
+ # puts "Converting %s (%s)" % [key, value.inspect]
+ # p value
+ # value.to_json(*args)
+ # key.to_json(*args)
+ #end
+ #puts "Converted all"
+ #p res
+ res.to_json(*args)
+ end
+
# Proxy these methods to the parameters hash. It's likely they'll
# be overridden at some point, but this works for now.
%w{has_key? keys length delete empty? <<}.each do |method|
@@ -83,9 +152,6 @@ class Puppet::Resource
unless result.include?(namevar)
result[namevar] = title
end
- if result.has_key?(nil)
- raise "wtf? %s" % namevar.inspect
- end
result
end
diff --git a/spec/unit/resource.rb b/spec/unit/resource.rb
index 5d838b233..c993f8d98 100755
--- a/spec/unit/resource.rb
+++ b/spec/unit/resource.rb
@@ -353,4 +353,156 @@ describe Puppet::Resource do
end
end
end
+
+ describe "when converting to json" do
+ confine "Missing 'json' library" => Puppet.features.json?
+
+ def json_output_should
+ @resource.class.expects(:json_create).with { |hash| yield hash }
+ end
+
+ it "should include the json util module" do
+ Puppet::Resource.metaclass.ancestors.should be_include(Puppet::Util::Json)
+ end
+
+ # LAK:NOTE For all of these tests, we convert back to the resource so we can
+ # trap the actual data structure then.
+ it "should set its json_class to 'Puppet::Resource'" do
+ JSON.parse(Puppet::Resource.new("file", "yay").to_json).should be_instance_of(Puppet::Resource)
+ end
+
+ it "should set its type to the provided type" do
+ JSON.parse(Puppet::Resource.new("File", "/foo").to_json).type.should == "File"
+ end
+
+ it "should set its title to the provided title" do
+ JSON.parse(Puppet::Resource.new("File", "/foo").to_json).title.should == "/foo"
+ end
+
+ it "should include all tags from the resource" do
+ resource = Puppet::Resource.new("File", "/foo")
+ resource.tag("yay")
+
+ JSON.parse(resource.to_json).tags.should == resource.tags
+ end
+
+ it "should include the file if one is set" do
+ resource = Puppet::Resource.new("File", "/foo")
+ resource.file = "/my/file"
+
+ JSON.parse(resource.to_json).file.should == "/my/file"
+ end
+
+ it "should include the line if one is set" do
+ resource = Puppet::Resource.new("File", "/foo")
+ resource.line = 50
+
+ JSON.parse(resource.to_json).line.should == 50
+ end
+
+ it "should include the 'exported' value if one is set" do
+ resource = Puppet::Resource.new("File", "/foo")
+ resource.exported = true
+
+ JSON.parse(resource.to_json).exported.should be_true
+ end
+
+ it "should set 'exported' to false if no value is set" do
+ resource = Puppet::Resource.new("File", "/foo")
+
+ JSON.parse(resource.to_json).exported.should be_false
+ end
+
+ it "should set all of its parameters as the 'parameters' entry" do
+ resource = Puppet::Resource.new("File", "/foo")
+ resource[:foo] = %w{bar eh}
+ resource[:fee] = %w{baz}
+
+ result = JSON.parse(resource.to_json)
+ result["foo"].should == %w{bar eh}
+ result["fee"].should == %w{baz}
+ end
+
+ it "should set all parameter values as arrays" do
+ resource = Puppet::Resource.new("File", "/foo")
+ resource[:foo] = "bar"
+ JSON.parse(resource.to_json)["foo"].should == %w{bar}
+ end
+ end
+
+ describe "when converting from json" do
+ confine "Missing 'json' library" => Puppet.features.json?
+
+ def json_result_should
+ Puppet::Resource.expects(:new).with { |hash| yield hash }
+ end
+
+ before do
+ @data = {
+ 'type' => "file",
+ 'title' => "yay",
+ }
+ end
+
+ it "should set its type to the provided type" do
+ Puppet::Resource.from_json(@data).type.should == "File"
+ end
+
+ it "should set its title to the provided title" do
+ Puppet::Resource.from_json(@data).title.should == "yay"
+ end
+
+ it "should set its title to the provided title" do
+ Puppet::Resource.from_json(@data).title.should == "yay"
+ end
+
+ it "should tag the resource with any provided tags" do
+ @data['tags'] = %w{foo bar}
+ resource = Puppet::Resource.from_json(@data)
+ resource.tags.should be_include("foo")
+ resource.tags.should be_include("bar")
+ end
+
+ it "should set its file to the provided file" do
+ @data['file'] = "/foo/bar"
+ Puppet::Resource.from_json(@data).file.should == "/foo/bar"
+ end
+
+ it "should set its line to the provided line" do
+ @data['line'] = 50
+ Puppet::Resource.from_json(@data).line.should == 50
+ end
+
+ it "should 'exported' to true if set in the json data" do
+ @data['exported'] = true
+ Puppet::Resource.from_json(@data).exported.should be_true
+ end
+
+ it "should 'exported' to false if not set in the json data" do
+ Puppet::Resource.from_json(@data).exported.should be_false
+ end
+
+ it "should fail if no title is provided" do
+ @data.delete('title')
+ lambda { Puppet::Resource.from_json(@data) }.should raise_error(ArgumentError)
+ end
+
+ it "should fail if no type is provided" do
+ @data.delete('type')
+ lambda { Puppet::Resource.from_json(@data) }.should raise_error(ArgumentError)
+ end
+
+ it "should set each of the provided parameters" do
+ @data['parameters'] = {'foo' => %w{one two}, 'fee' => %w{three four}}
+ resource = Puppet::Resource.from_json(@data)
+ resource['foo'].should == %w{one two}
+ resource['fee'].should == %w{three four}
+ end
+
+ it "should convert single-value array parameters to normal values" do
+ @data['parameters'] = {'foo' => %w{one}}
+ resource = Puppet::Resource.from_json(@data)
+ resource['foo'].should == %w{one}
+ end
+ end
end