summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jacob <adam@hjksolutions.com>2008-03-07 17:28:27 -0800
committerAdam Jacob <adam@hjksolutions.com>2008-03-07 17:28:27 -0800
commitb4beed548959ca63365ca3d799c59a155047b5ff (patch)
tree91207c05fb2517b1b87b0eb1f3deb111d6b058d9
parentaca232ba638afdc45f6d5b3e9b3f68d4a149d0a5 (diff)
downloadchef-b4beed548959ca63365ca3d799c59a155047b5ff.tar.gz
Syntax is right in the recipes
-rwxr-xr-xbin/marionette-dotgraph40
-rw-r--r--docs/recipe.rb61
-rw-r--r--examples/mrepo/Rakefile (renamed from bin/marionette)0
-rw-r--r--examples/sample_recipe.rb69
-rw-r--r--lib/marionette/mixin/check_arguments.rb (renamed from lib/marionette/helper.rb)15
-rw-r--r--lib/marionette/mixin/graph_resources.rb8
-rw-r--r--lib/marionette/recipe.rb34
-rw-r--r--lib/marionette/resource.rb123
-rw-r--r--lib/marionette/resource/file.rb102
-rw-r--r--spec/lib/marionette/resource/zen_master.rb44
-rw-r--r--spec/spec.opts5
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/unit/mixin/graph_resources_spec.rb41
-rw-r--r--spec/unit/node.rb43
-rw-r--r--spec/unit/recipe_spec.rb20
-rw-r--r--spec/unit/resource/file_spec.rb44
-rw-r--r--spec/unit/resource_spec.rb117
-rw-r--r--tasks/rspec.rb52
18 files changed, 631 insertions, 189 deletions
diff --git a/bin/marionette-dotgraph b/bin/marionette-dotgraph
new file mode 100755
index 0000000000..80e2f342d7
--- /dev/null
+++ b/bin/marionette-dotgraph
@@ -0,0 +1,40 @@
+#!/usr/bin/ruby
+#
+# Author:: Adam Jacob (<adam@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 HJK Solutions, LLC
+# License:: GNU General Public License version 2 or later
+#
+# This program and entire repository is free software; you can
+# redistribute it and/or modify it under the terms of the GNU
+# General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+require File.join(File.dirname(__FILE__), "..", "lib", "marionette")
+require 'rgl/dot'
+
+mr = Marionette::Recipe.new("test", "default", "node")
+raise ArgumentError, "#{ARGV[0]} is not a file!" unless File.exists?(ARGV[0])
+mr.instance_eval(IO.read(ARGV[0]), ARGV[0], 1)
+puts mr.inspect
+puts mr.dg.directed?
+puts mr.dg.acyclic?
+tree = Array.new
+mr.dg.depth_first_visit(:top) do |v|
+ tree << v
+end
+maybe = mr.dg.bfs_search_tree_from(:top)
+puts maybe.acyclic?
+puts maybe.directed?
+puts maybe.topsort_iterator.to_a.join("\n")
+maybe.write_to_graphic_file
+
diff --git a/docs/recipe.rb b/docs/recipe.rb
index 6c06a403e4..66d8b4c089 100644
--- a/docs/recipe.rb
+++ b/docs/recipe.rb
@@ -5,22 +5,57 @@ include_recipe 'openldap::client'
include_recipe 'openssh'
include_recipe 'nscd'
-remote_file "nsswitch.conf" do
- path "/etc/nsswitch.conf"
- source "nsswitch.conf"
- module "openldap"
- mode 0644
- owner "root"
- group "root"
+file "/etc/nsswitch.conf" {
+ insure = "present"
+ owner = "root"
+ group = "root"
+ mode = 0644
+}
+
+file "/etc/ldap.conf" {
+ insure = "present"
+ owner = "root"
+ group = "root"
+ mode = 0644
+ requires = resources(:file => "/etc/nsswitch.conf")
+}
+
+file "/etc/ldap.conf" do
+ insure = "present"
+ owner = "root"
+ group = "root"
+ mode = 0644
+ requires = resources(:file => "/etc/nsswitch.conf")
+end
+
+remote_file "nsswitch.conf" {
+ path "/etc/nsswitch.conf"
+ source "nsswitch.conf"
+ module "openldap"
+ mode 0644
+ owner "root"
+ group "root"
requires :file => "nsswitch-ldap-file", :exec => [ "one", "two" ]
- requires = resource(:file => "nsswitch-ldap-file")
- notifies = resource(:service => "nscd", :exec => [ "nscd-clear-passwd", "nscd-clear-group" ] )
- subscribes =
+ notifies :service => "nscd", :exec => [ "nscd-clear-passwd", "nscd-clear-group" ]
+ provider 'File::Rsync'
+}
+
+remote_file "nsswitch.conf" {
+ path = "/etc/nsswitch.conf"
+ source = "nsswitch.conf"
+ module = "openldap"
+ mode = 0644
+ owner = "root"
+ group = "root"
+ requires = resources :file => "nsswitch-ldap-file",
+ :exec => [ "one", "two" ]
+ notifies = resources :service => "nscd",
+ :exec => [ "nscd-clear-passwd", "nscd-clear-group" ]
provider = 'File::Rsync'
-end
+}
service "nscd" do |s|
- s.ensure = "running"
+ s.insure = "running"
end
case node[:lsbdistid]
@@ -36,7 +71,7 @@ when "CentOS"
f.require = resource(:package => "nss_ldap")
end
package "nss_ldap" do |p|
- p.ensure = "latest"
+ p.insure = "latest"
end
end
diff --git a/bin/marionette b/examples/mrepo/Rakefile
index e69de29bb2..e69de29bb2 100644
--- a/bin/marionette
+++ b/examples/mrepo/Rakefile
diff --git a/examples/sample_recipe.rb b/examples/sample_recipe.rb
new file mode 100644
index 0000000000..730d7d58ff
--- /dev/null
+++ b/examples/sample_recipe.rb
@@ -0,0 +1,69 @@
+include_recipe "openldap"
+include_recipe "openldap::client"
+include_recipe "openldap::server"
+include_recipe "resolver"
+include_recipe "base"
+
+service "apache2" do
+ insure "running"
+ has_restart true
+end
+
+file "/etc/nsswitch.conf" do
+ insure "present"
+ owner "root"
+ group "root"
+ mode 0644
+ notify :restart, resources(:service => "openldap"), :immediately
+end
+
+file "/etc/ldap.conf" do
+ insure "present"
+ owner "root"
+ group "root"
+ mode 0644
+ requires resources(:file => "/etc/nsswitch.conf")
+end
+
+file "/srv/monkey" do
+ insure "present"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+file "/srv/owl" do
+ insure "present"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+file "/srv/zen" do
+ insure "absent"
+end
+
+#
+# file "/srv/monkey" do |f|
+# f.insure = "present"
+# f.owner = "adam"
+# f.group = "adam"
+# f.mode = 0644
+# f.before = resources(:file => "/etc/nsswitch.conf")
+# end
+#
+# file "/etc/ldap-nss.conf" do |f|
+# f.insure = "present"
+# f.owner = "root"
+# f.group = "root"
+# f.mode = 0644
+# f.notifies = :refresh, resources(:file => "/etc/ldap.conf")
+# end
+#
+# file "/etc/coffee.conf" do |f|
+# f.insure = "present"
+# f.owner = "root"
+# f.group = "root"
+# f.mode = 0644
+# f.subscribes = :polio, resources(:file => "/etc/nsswitch.conf")
+# end \ No newline at end of file
diff --git a/lib/marionette/helper.rb b/lib/marionette/mixin/check_arguments.rb
index 922f9449e1..ba38e3e734 100644
--- a/lib/marionette/helper.rb
+++ b/lib/marionette/mixin/check_arguments.rb
@@ -15,10 +15,19 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
+#
class Marionette
- module Helper
-
+ module Mixin
+ module CheckArguments
+ def check_symbol_or_string(to_check, field_name)
+ case to_check
+ when Symbol, String
+ true
+ else
+ raise ArgumentError, "you must pass a symbol or string to #{field_name}!"
+ end
+ end
+ end
end
end \ No newline at end of file
diff --git a/lib/marionette/mixin/graph_resources.rb b/lib/marionette/mixin/graph_resources.rb
index 0a9ebeab21..7721b5d91a 100644
--- a/lib/marionette/mixin/graph_resources.rb
+++ b/lib/marionette/mixin/graph_resources.rb
@@ -17,6 +17,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
+require 'rubygems'
+require 'rgl/adjacency'
+require 'rgl/topsort'
+require 'rgl/dot'
+
class Marionette
module Mixin
module GraphResources
@@ -26,7 +31,7 @@ class Marionette
# Returns one or an Array of matching resources.
#
# Raises a Runtime Error if it can't find the resources you are looking for.
- def resource(args)
+ def resources(args)
unless args.kind_of?(Hash)
raise ArgumentError, "resource requires a hash of :resources => names"
end
@@ -73,7 +78,6 @@ class Marionette
end
raise RuntimeError, msg
end
-
results.length == 1 ? results[0][:object] : results.collect { |r| r[:object] }
end
end
diff --git a/lib/marionette/recipe.rb b/lib/marionette/recipe.rb
index 7a9dc916de..e008400d55 100644
--- a/lib/marionette/recipe.rb
+++ b/lib/marionette/recipe.rb
@@ -18,18 +18,14 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
-require 'rubygems'
-require 'rgl/adjacency'
-require 'rgl/topsort'
-
class Marionette
class Recipe
include Marionette::Mixin::GraphResources
- attr_accessor :module_name, :recipe_name, :recipe, :node, :dg
+ attr_accessor :module_name, :recipe_name, :recipe, :node, :dg, :deps
- def initialize(module_name, recipe_name, node, dg=nil)
+ def initialize(module_name, recipe_name, node, dg=nil, deps=nil)
@module_name = module_name
@recipe_name = recipe_name
@node = node
@@ -39,7 +35,13 @@ class Marionette
@dg = RGL::DirectedAdjacencyGraph.new()
@dg.add_vertex(:top)
end
+ if deps
+ @deps = deps
+ else
+ @deps = RGL::DirectedAdjacencyGraph.new()
+ end
@last_resource = :top
+ @in_order = Array.new
end
def method_missing(method_symbol, *args, &block)
@@ -54,25 +56,19 @@ class Marionette
end
begin
args << @dg
+ args << @deps
resource = eval(rname).new(*args)
- resource.run(block) if Kernel.block_given?
+ resource.instance_eval(&block)
rescue Exception => e
- raise NameError, "Cannot find #{rname} for #{method_name}\nOriginal: #{e.to_s}" if e.kind_of?(NameError)
- raise e
+ if e.kind_of?(NameError) && e.to_s =~ /Marionette::Resource/
+ raise NameError, "Cannot find #{rname} for #{method_name}\nOriginal: #{e.to_s}"
+ else
+ raise e
+ end
end
@dg.add_vertex(resource)
@dg.add_edge(@last_resource, resource)
@last_resource = resource
end
-
- private
- def check_symbol_or_string(to_check, field_name)
- case to_check
- when Symbol, String
- true
- else
- raise ArgumentError, "you must pass a symbol or string to #{field_name}!"
- end
- end
end
end \ No newline at end of file
diff --git a/lib/marionette/resource.rb b/lib/marionette/resource.rb
index f7ca861ccf..3100c2d7cb 100644
--- a/lib/marionette/resource.rb
+++ b/lib/marionette/resource.rb
@@ -17,6 +17,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
+require 'rubygems'
require 'yaml'
class Marionette
@@ -24,58 +25,130 @@ class Marionette
include Marionette::Mixin::GraphResources
- attr_accessor :before, :requires, :notifies, :subscribes, :tag
- attr_reader :name, :alias, :noop, :tag, :resource_name, :dg
+ attr_accessor :tag, :actions
+ attr_reader :name, :noop, :tag, :resource_name, :dg, :deps, :notifies, :subscribes
- def initialize(name, dg=nil)
+ def initialize(name, dg=nil, deps=nil)
@name = name
if dg
@dg = dg
else
@dg = RGL::DirectedAdjacencyGraph.new()
- @dg.add_vertex(:top)
end
- @tag = Array.new
- @alias = nil
+ if deps
+ @deps = deps
+ else
+ @deps = RGL::DirectedAdjacencyGraph.new()
+ end
+ @tag = [ name.to_s ]
@noop = nil
@tag = nil
@before = nil
- @tag = nil
+ @actions = Hash.new
end
- def name=(name)
- raise ArgumentError, "name must be a string!" unless name.kind_of?(String)
- @name = name
+ def name(name=nil)
+ set_if_args(@name, name) do
+ raise ArgumentError, "name must be a string!" unless name.kind_of?(String)
+ @name = name
+ end
end
- def alias=(alias_name)
- raise ArgumentError, "alias must be a string!" unless alias_name.kind_of?(String)
- @alias = alias_name
+ def noop(tf=nil)
+ set_if_args(@noop, tf) do
+ raise ArgumentError, "noop must be true or false!" unless tf == true || tf == false
+ @noop = tf
+ end
end
- def noop=(tf)
- raise ArgumentError, "noop must be true or false!" unless tf == true || tf == false
- @noop = tf
+ def requires(resources=nil)
+ rarray = resources.kind_of?(Array) ? resources : [ resources ]
+ rarray.each do |resource|
+ @deps.add_vertex(self)
+ @deps.add_vertex(resource)
+ @deps.add_edge(resource, self)
+ end
+ true
+ end
+
+ def before(resources)
+ rarray = resources.kind_of?(Array) ? resources : [ resources ]
+ rarray.each do |resource|
+ @deps.add_vertex(self)
+ @deps.add_vertex(resource)
+ @deps.add_edge(self, resource)
+ end
+ true
end
- def tag=(args)
- if args.kind_of?(Array)
- args.each do |t|
- @tag << t
+ def notifies(*notify_actions)
+ resources = notify_actions.pop
+ rarray = resources.kind_of?(Array) ? resources : [ resources ]
+ rarray.each do |resource|
+ @deps.add_vertex(self)
+ @deps.add_vertex(resource)
+ @deps.add_edge(self, resource)
+ notify_actions.each do |action|
+ action_sym = action.to_sym
+ if @actions.has_key?(action_sym)
+ @actions[action_sym] << resource
+ else
+ @actions[action_sym] = [ resource ]
+ end
end
- else
- @tag << args
end
- @tag
+ true
end
- def run(ourblock)
- ourblock.call
+ def subscribes(*subscribe_actions)
+ resources = subscribe_actions.pop
+ rarray = resources.kind_of?(Array) ? resources : [ resources ]
+ rarray.each do |resource|
+ @deps.add_vertex(self)
+ @deps.add_vertex(resource)
+ @deps.add_edge(resource, self)
+ subscribe_actions.each do |action|
+ action_sym = action.to_sym
+ if @actions.has_key?(action_sym)
+ resource.actions[action_sym] << self
+ else
+ resource.actions[action_sym] = [ self ]
+ end
+ end
+ end
+ true
+ end
+
+ def tag(args=nil)
+ set_if_args(@tag, args) do
+ if args.kind_of?(Array)
+ args.each do |t|
+ @tag << t
+ end
+ else
+ @tag << args
+ end
+ @tag
+ end
+ end
+
+ def to_s
+ "#{@resource_name} #{@name}"
end
def valid?()
return false unless self.name
true
end
+
+ private
+ def set_if_args(thing, arguments)
+ raise ArgumentError, "Must call set_if_args with a block!" unless Kernel.block_given?
+ if arguments != nil
+ yield(arguments)
+ else
+ thing
+ end
+ end
end
end \ No newline at end of file
diff --git a/lib/marionette/resource/file.rb b/lib/marionette/resource/file.rb
index 001474c8f9..f19b8f7b17 100644
--- a/lib/marionette/resource/file.rb
+++ b/lib/marionette/resource/file.rb
@@ -20,9 +20,9 @@
class Marionette
class Resource
class File < Marionette::Resource
- attr_reader :backup, :checksum, :ensure, :group, :mode, :owner, :path
+ attr_reader :backup, :checksum, :insure, :group, :mode, :owner, :path
- def initialize(name, dg=nil)
+ def initialize(name, dg=nil, deps=nil)
@resource_name = :file
super(name, dg)
@path = name
@@ -30,66 +30,80 @@ class Marionette
@checksum = "md5sum"
end
- def backup=(arg)
- case arg
- when true, false, Integer
- @backup = arg
- else
- raise ArgumentError, "backup must be true, false, or a number!"
+ def backup(arg=nil)
+ set_if_args(@backup, arg) do
+ case arg
+ when true, false, Integer
+ @backup = arg
+ else
+ raise ArgumentError, "backup must be true, false, or a number!"
+ end
end
end
- def checksum=(arg)
- case arg
- when "md5sum", "mtime"
- @checksum = arg
- else
- raise ArgumentError, "checksum must be md5sum or mtime!"
+ def checksum(arg=nil)
+ set_if_args(@checksum, arg) do
+ case arg
+ when "md5sum", "mtime"
+ @checksum = arg
+ else
+ raise ArgumentError, "checksum must be md5sum or mtime!"
+ end
end
end
- def ensure=(arg)
- case arg
- when "absent", "present"
- @ensure = arg
- else
- raise ArgumentError, "ensure must be absent or present!"
+ def insure(arg=nil)
+ set_if_args(@insure, arg) do
+ case arg
+ when "absent", "present"
+ @insure = arg
+ else
+ raise ArgumentError, "insure must be absent or present!"
+ end
end
end
- def group=(arg)
- case arg
- when /^([a-z]|[A-Z]|[0-9]|_|-)+$/, Integer
- @group = arg
- else
- raise ArgumentError, "group must match /^([a-z]|[A-Z]|[0-9]|_|-)$/, Integer!"
+ def group(arg=nil)
+ set_if_args(@group, arg) do
+ case arg
+ when /^([a-z]|[A-Z]|[0-9]|_|-)+$/, Integer
+ @group = arg
+ else
+ raise ArgumentError, "group must match /^([a-z]|[A-Z]|[0-9]|_|-)$/, Integer!"
+ end
end
end
- def mode=(arg)
- case "#{arg.to_s}"
- when /^\d{3,4}$/
- @mode = arg
- else
- raise ArgumentError, "mode must be a valid unix file mode - 3 or 4 digets!"
+ def mode(arg=nil)
+ set_if_args(@mode, arg) do
+ case "#{arg.to_s}"
+ when /^\d{3,4}$/
+ @mode = arg
+ else
+ raise ArgumentError, "mode must be a valid unix file mode - 3 or 4 digets!"
+ end
end
end
- def owner=(arg)
- case arg
- when /^([a-z]|[A-Z]|[0-9]|_|-)+$/, Integer
- @group = arg
- else
- raise ArgumentError, "group must match /^([a-z]|[A-Z]|[0-9]|_|-)$/, Integer!"
+ def owner(arg=nil)
+ set_if_args(@owner, arg) do
+ case arg
+ when /^([a-z]|[A-Z]|[0-9]|_|-)+$/, Integer
+ @owner = arg
+ else
+ raise ArgumentError, "group must match /^([a-z]|[A-Z]|[0-9]|_|-)$/, Integer!"
+ end
end
end
- def path=(arg)
- case arg
- when String
- @path = arg
- else
- raise ArgumentError, "path must be a string!"
+ def path(arg=nil)
+ set_if_args(@path, arg) do
+ case arg
+ when String
+ @path = arg
+ else
+ raise ArgumentError, "path must be a string!"
+ end
end
end
diff --git a/spec/lib/marionette/resource/zen_master.rb b/spec/lib/marionette/resource/zen_master.rb
new file mode 100644
index 0000000000..31b300d841
--- /dev/null
+++ b/spec/lib/marionette/resource/zen_master.rb
@@ -0,0 +1,44 @@
+# Author:: Adam Jacob (<adam@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 HJK Solutions, LLC
+# License:: GNU General Public License version 2 or later
+#
+# This program and entire repository is free software; you can
+# redistribute it and/or modify it under the terms of the GNU
+# General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+class Marionette
+ class Resource
+ class ZenMaster < Marionette::Resource
+ attr_reader :peace
+
+ def initialize(name, dg=nil, deps=nil)
+ @resource_name = :zen_master
+ super(name, dg)
+ end
+
+ def peace(tf)
+ @peace = tf
+ end
+
+ def something(arg=nil)
+ set_if_args(@something, arg) do
+ case arg
+ when true, false
+ @something = arg
+ end
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/spec.opts b/spec/spec.opts
new file mode 100644
index 0000000000..f94cf2d923
--- /dev/null
+++ b/spec/spec.opts
@@ -0,0 +1,5 @@
+--color
+--format
+progress
+--loadby
+mtime
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 314c81a5d9..452da0c2a3 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -18,3 +18,5 @@
#
require File.join(File.dirname(__FILE__), "..", "lib", "marionette")
+Dir[File.join(File.dirname(__FILE__), 'lib', '**', '*.rb')].sort.each { |lib| require lib }
+
diff --git a/spec/unit/mixin/graph_resources_spec.rb b/spec/unit/mixin/graph_resources_spec.rb
new file mode 100644
index 0000000000..9fbb4f4c3e
--- /dev/null
+++ b/spec/unit/mixin/graph_resources_spec.rb
@@ -0,0 +1,41 @@
+#
+# Author:: Adam Jacob (<adam@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 HJK Solutions, LLC
+# License:: GNU General Public License version 2 or later
+#
+# This program and entire repository is free software; you can
+# redistribute it and/or modify it under the terms of the GNU
+# General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+require File.join(File.dirname(__FILE__), "..", "..", "spec_helper")
+
+describe Marionette::Mixin::GraphResources do
+ it "should find a resource by symbol and name, or array of names" do
+ @recipe = Marionette::Recipe.new("one", "two", "three")
+ %w{monkey dog cat}.each do |name|
+ @recipe.zen_master name do
+ peace = true
+ end
+ end
+ doggie = @recipe.resources(:zen_master => "dog")
+ doggie.name.should eql("dog") # clever, I know
+ multi_zen = [ "dog", "monkey" ]
+ zen_array = @recipe.resources(:zen_master => multi_zen)
+ zen_array.length.should eql(2)
+ zen_array.each_index do |i|
+ zen_array[i].name.should eql(multi_zen[i])
+ zen_array[i].resource_name.should eql(:zen_master)
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/node.rb b/spec/unit/node.rb
new file mode 100644
index 0000000000..57c8cdd7f1
--- /dev/null
+++ b/spec/unit/node.rb
@@ -0,0 +1,43 @@
+# Author:: Adam Jacob (<adam@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 HJK Solutions, LLC
+# License:: GNU General Public License version 2 or later
+#
+# This program and entire repository is free software; you can
+# redistribute it and/or modify it under the terms of the GNU
+# General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+require File.join(File.dirname(__FILE__), "..", "spec_helper")
+
+describe Marionette::Node do
+ before(:each) do
+ @node = Marionette::Node.new("latte")
+ end
+
+ it "should have a name" do
+ @resource.name.should eql("latte")
+ end
+
+ it "should create a new Marionette::Node" do
+ @resource.should be_a_kind_of(Marionette::Node)
+ end
+
+ it "should not be valid without a name" do
+ lambda { @resource.name = nil }.should raise_error(ArgumentError)
+ end
+
+ it "should always have a string for name" do
+ lambda { @resource.name = Hash.new }.should raise_error(ArgumentError)
+ end
+
+end \ No newline at end of file
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index 66c6095ffc..69f70e6862 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -19,24 +19,6 @@
require File.join(File.dirname(__FILE__), "..", "spec_helper")
-class Marionette
- class Resource
- class ZenMaster < Marionette::Resource
- attr_reader :peace
-
- def initialize(name, dg)
- @resource_name = :zen_master
- super(name, dg)
- end
-
- def peace=(tf)
- @peace = tf
- end
- end
- end
-end
-
-
describe Marionette::Recipe do
before(:each) do
@recipe = Marionette::Recipe.new("hjk", "test", "node")
@@ -89,7 +71,7 @@ zen_master "gnome" do
end
CODE
lambda { @recipe.instance_eval(code) }.should_not raise_error
- @recipe.resource(:zen_master => "gnome").name.should eql("gnome")
+ @recipe.resources(:zen_master => "gnome").name.should eql("gnome")
end
end \ No newline at end of file
diff --git a/spec/unit/resource/file_spec.rb b/spec/unit/resource/file_spec.rb
index 633805b56c..62b6498473 100644
--- a/spec/unit/resource/file_spec.rb
+++ b/spec/unit/resource/file_spec.rb
@@ -39,10 +39,10 @@ describe Marionette::Resource::File do
end
it "should only accept true, false, or a number for backup" do
- lambda { @resource.backup = true }.should_not raise_error(ArgumentError)
- lambda { @resource.backup = false }.should_not raise_error(ArgumentError)
- lambda { @resource.backup = 10 }.should_not raise_error(ArgumentError)
- lambda { @resource.backup = "blues" }.should raise_error(ArgumentError)
+ lambda { @resource.backup true }.should_not raise_error(ArgumentError)
+ lambda { @resource.backup false }.should_not raise_error(ArgumentError)
+ lambda { @resource.backup 10 }.should_not raise_error(ArgumentError)
+ lambda { @resource.backup "blues" }.should raise_error(ArgumentError)
end
it "should use the md5sum for checking changes by default" do
@@ -50,33 +50,33 @@ describe Marionette::Resource::File do
end
it "should accept md5sum or mtime for checksum" do
- lambda { @resource.checksum = "md5sum" }.should_not raise_error(ArgumentError)
- lambda { @resource.checksum = "mtime" }.should_not raise_error(ArgumentError)
- lambda { @resource.checksum = "blues" }.should raise_error(ArgumentError)
+ lambda { @resource.checksum "md5sum" }.should_not raise_error(ArgumentError)
+ lambda { @resource.checksum "mtime" }.should_not raise_error(ArgumentError)
+ lambda { @resource.checksum "blues" }.should raise_error(ArgumentError)
end
- it "should accept absent or present for ensure" do
- lambda { @resource.ensure = "absent" }.should_not raise_error(ArgumentError)
- lambda { @resource.ensure = "present" }.should_not raise_error(ArgumentError)
- lambda { @resource.ensure = "blues" }.should raise_error(ArgumentError)
+ it "should accept absent or present for insure" do
+ lambda { @resource.insure "absent" }.should_not raise_error(ArgumentError)
+ lambda { @resource.insure "present" }.should_not raise_error(ArgumentError)
+ lambda { @resource.insure "blues" }.should raise_error(ArgumentError)
end
it "should accept a group name or id for group" do
- lambda { @resource.group = "root" }.should_not raise_error(ArgumentError)
- lambda { @resource.group = 123 }.should_not raise_error(ArgumentError)
- lambda { @resource.group = "root*goo" }.should raise_error(ArgumentError)
+ lambda { @resource.group "root" }.should_not raise_error(ArgumentError)
+ lambda { @resource.group 123 }.should_not raise_error(ArgumentError)
+ lambda { @resource.group "root*goo" }.should raise_error(ArgumentError)
end
it "should accept a valid unix file mode" do
- lambda { @resource.mode = 0444 }.should_not raise_error(ArgumentError)
- lambda { @resource.mode = 444 }.should_not raise_error(ArgumentError)
- lambda { @resource.mode = 4 }.should raise_error(ArgumentError)
+ lambda { @resource.mode 0444 }.should_not raise_error(ArgumentError)
+ lambda { @resource.mode 444 }.should_not raise_error(ArgumentError)
+ lambda { @resource.mode 4 }.should raise_error(ArgumentError)
end
it "should accept a user name or id for owner" do
- lambda { @resource.owner = "root" }.should_not raise_error(ArgumentError)
- lambda { @resource.owner = 123 }.should_not raise_error(ArgumentError)
- lambda { @resource.owner = "root*goo" }.should raise_error(ArgumentError)
+ lambda { @resource.owner "root" }.should_not raise_error(ArgumentError)
+ lambda { @resource.owner 123 }.should_not raise_error(ArgumentError)
+ lambda { @resource.owner "root*goo" }.should raise_error(ArgumentError)
end
it "should use the object name as the path by default" do
@@ -84,8 +84,8 @@ describe Marionette::Resource::File do
end
it "should accept a string as the path" do
- lambda { @resource.path = "/tmp" }.should_not raise_error(ArgumentError)
- lambda { @resource.path = Hash.new }.should raise_error(ArgumentError)
+ lambda { @resource.path "/tmp" }.should_not raise_error(ArgumentError)
+ lambda { @resource.path Hash.new }.should raise_error(ArgumentError)
end
end \ No newline at end of file
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index 3d4b8bfa66..ccabda6043 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -33,54 +33,93 @@ describe Marionette::Resource do
end
it "should not be valid without a name" do
- lambda { @resource.name = nil }.should raise_error(ArgumentError)
+ lambda { @resource.name false }.should raise_error(ArgumentError)
end
it "should always have a string for name" do
- lambda { @resource.name = Hash.new }.should raise_error(ArgumentError)
+ lambda { @resource.name Hash.new }.should raise_error(ArgumentError)
end
- it "should have a string for alias" do
- lambda { @resource.alias = nil }.should raise_error(ArgumentError)
- lambda { @resource.alias = 'foo' }.should_not raise_error(ArgumentError)
- @resource.alias.should eql("foo")
+ it "should accept true or false for noop" do
+ lambda { @resource.noop true }.should_not raise_error(ArgumentError)
+ lambda { @resource.noop false }.should_not raise_error(ArgumentError)
+ lambda { @resource.noop "eat it" }.should raise_error(ArgumentError)
end
- it "should accept true or false for noop" do
- lambda { @resource.noop = true }.should_not raise_error(ArgumentError)
- lambda { @resource.noop = false }.should_not raise_error(ArgumentError)
- lambda { @resource.noop = "eat it" }.should raise_error(ArgumentError)
+ it "should make itself dependent on required resources" do
+ lambda {
+ @resource.dg.add_vertex(Marionette::Resource::ZenMaster.new("coffee"))
+ }.should_not raise_error
+ lambda {
+ @resource.requires @resource.resources(:zen_master => "coffee")
+ }.should_not raise_error
+
+ @resource.deps.topsort_iterator.to_a[0].name.should eql("coffee")
+ @resource.deps.topsort_iterator.to_a[1].name.should eql("funk")
+ end
+
+ it "should make before resources appear later in the graph" do
+ lambda {
+ @resource.dg.add_vertex(Marionette::Resource::ZenMaster.new("coffee"))
+ }.should_not raise_error
+ lambda {
+ @resource.before @resource.resources(:zen_master => "coffee")
+ }.should_not raise_error
+
+ @resource.deps.topsort_iterator.to_a[0].name.should eql("funk")
+ @resource.deps.topsort_iterator.to_a[1].name.should eql("coffee")
+ end
+
+ it "should make notified resources appear in the actions hash" do
+ @resource.dg.add_vertex(Marionette::Resource::ZenMaster.new("coffee"))
+ @resource.notifies :reload, @resource.resources(:zen_master => "coffee")
+ @resource.actions[:reload][0].name.should eql("coffee")
+ end
+
+ it "should make notified resources happen later in the graph" do
+ @resource.dg.add_vertex(Marionette::Resource::ZenMaster.new("coffee"))
+ @resource.notifies :reload, @resource.resources(:zen_master => "coffee")
+ @resource.deps.topsort_iterator.to_a[0].name.should eql("funk")
+ @resource.deps.topsort_iterator.to_a[1].name.should eql("coffee")
end
- it "should serialize to yaml" do
- yaml_output = <<-DESC
---- !ruby/object:Marionette::Resource
-alias:
-before:
-name: funk
-noop:
-notify:
-require:
-subscribe:
-tag:
-DESC
- @resource.to_yaml.should eql(yaml_output)
- end
+ it "should make subscribed resources appear in the actions hash" do
+ @resource.dg.add_vertex(Marionette::Resource::ZenMaster.new("coffee"))
+ zr = @resource.resources(:zen_master => "coffee")
+ @resource.subscribes :reload, zr
+ zr.actions[:reload][0].name.should eql("funk")
+ end
+
+ it "should make subscribed resources happen earlier in the graph" do
+ @resource.dg.add_vertex(Marionette::Resource::ZenMaster.new("coffee"))
+ zr = @resource.resources(:zen_master => "coffee")
+ @resource.subscribes :reload, zr
+ @resource.deps.topsort_iterator.to_a[1].name.should eql("funk")
+ @resource.deps.topsort_iterator.to_a[0].name.should eql("coffee")
+ end
- it "should find a resource by symbol and name, or array of names" do
- # %w{monkey dog cat}.each do |name|
- # @recipe.zen_master name do
- # peace = true
- # end
- # end
- # doggie = @recipe.resource(:zen_master => "dog")
- # doggie.name.should eql("dog") # clever, I know
- # multi_zen = [ "dog", "monkey" ]
- # zen_array = @recipe.resource(:zen_master => multi_zen)
- # zen_array.length.should eql(2)
- # zen_array.each_index do |i|
- # zen_array[i].name.should eql(multi_zen[i])
- # zen_array[i].resource_name.should eql(:zen_master)
- # end
+ it "should return a value if not defined" do
+ zm = Marionette::Resource::ZenMaster.new("coffee")
+ zm.something(true).should eql(true)
+ zm.something.should eql(true)
+ zm.something(false).should eql(false)
+ zm.something.should eql(false)
end
+
+# it "should serialize to yaml" do
+# yaml_output = <<-DESC
+#--- !ruby/object:Marionette::Resource
+#alias:
+#before:
+#name: funk
+#noop:
+#notify:
+#require:
+#subscribe:
+#tag:
+#DESC
+# @resource.to_yaml.should eql(yaml_output)
+# end
+
+
end \ No newline at end of file
diff --git a/tasks/rspec.rb b/tasks/rspec.rb
index f3c2d7d25b..077840d31d 100644
--- a/tasks/rspec.rb
+++ b/tasks/rspec.rb
@@ -2,7 +2,53 @@ require 'rubygems'
require 'rake'
require 'spec/rake/spectask'
-desc "Run all examples"
-Spec::Rake::SpecTask.new('spec') do |t|
- t.spec_files = FileList[File.join(File.dirname(__FILE__), "..", "spec", "**", "*.rb")]
+#desc "Run all examples"
+#Spec::Rake::SpecTask.new('spec') do |t|
+# t.spec_files = FileList[File.join(File.dirname(__FILE__), "..", "spec", "**", "*.rb")]
+#end
+
+require 'spec/rake/spectask'
+require 'spec/translator'
+
+MARIONETTE_ROOT = File.join(File.dirname(__FILE__), "..")
+
+task :default => :spec
+
+desc "Run all specs in spec directory"
+Spec::Rake::SpecTask.new(:spec) do |t|
+ t.spec_opts = ['--options', "\"#{MARIONETTE_ROOT}/spec/spec.opts\""]
+ t.spec_files = FileList['spec/**/*_spec.rb']
end
+
+namespace :spec do
+ desc "Run all specs in spec directory with RCov"
+ Spec::Rake::SpecTask.new(:rcov) do |t|
+ t.spec_opts = ['--options', "\"#{MARIONETTE_ROOT}/spec/spec.opts\""]
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.rcov = true
+ t.rcov_opts = lambda do
+ IO.readlines("#{MARIONETTE_ROOT}/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
+ end
+ end
+
+ desc "Print Specdoc for all specs"
+ Spec::Rake::SpecTask.new(:doc) do |t|
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ end
+
+ [:unit].each do |sub|
+ desc "Run the specs under spec/#{sub}"
+ Spec::Rake::SpecTask.new(sub) do |t|
+ t.spec_opts = ['--options', "\"#{MARIONETTE_ROOT}/spec/spec.opts\""]
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
+ end
+ end
+
+ desc "Translate/upgrade specs using the built-in translator"
+ task :translate do
+ translator = ::Spec::Translator.new
+ dir = MARIONETTE_ROOT + '/spec'
+ translator.translate(dir, dir)
+ end
+end \ No newline at end of file