#!/usr/bin/env rspec require 'spec_helper' require 'puppet/dsl/resource_api' describe Puppet::DSL::ResourceAPI do before do @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo")) @scope = Puppet::Parser::Scope.new(:compiler => @compiler, :source => "foo") @resource = Puppet::Parser::Resource.new(:mytype, "myresource", :scope => @scope) @api = Puppet::DSL::ResourceAPI.new(@resource, @scope, proc { }) end it "should include the resource type collection helper" do Puppet::DSL::ResourceAPI.ancestors.should be_include(Puppet::Resource::TypeCollectionHelper) end it "should use the scope's environment as its environment" do @scope.expects(:environment).returns "myenv" @api.environment.should == "myenv" end it "should be able to set all of its parameters as instance variables" do @resource["foo"] = "myval" @api.set_instance_variables @api.instance_variable_get("@foo").should == "myval" end describe "when calling a function" do it "should return false if the function does not exist" do Puppet::Parser::Functions.expects(:function).with("myfunc").returns nil @api.call_function("myfunc", "foo").should be_false end it "should use the scope the call the provided function with the provided arguments and return the results" do scope = stub 'scope' @api.stubs(:scope).returns scope Puppet::Parser::Functions.expects(:function).with("myfunc").returns "myfunc_method" scope.expects(:myfunc_method).with("one", "two") @api.call_function("myfunc", ["one", "two"]) end it "should call 'include' when asked to call 'acquire'" do scope = stub 'scope' @api.stubs(:scope).returns scope @api.stubs(:valid_type?).returns false scope.expects(:function_include).with("one", "two") @api.acquire("one", "two") end end describe "when determining if a provided name is a valid type" do it "should be valid if it's :class" do @api.should be_valid_type(:class) end it "should be valid if it's :node" do @api.should be_valid_type(:node) end it "should be valid if it's a builtin type" do Puppet::Type.expects(:type).with(:mytype).returns "whatever" @api.should be_valid_type(:mytype) end it "should be valid if it's a defined resource type in the environment's known resource types" do collection = stub 'collection' @api.stubs(:known_resource_types).returns collection collection.expects(:definition).with(:mytype).returns "whatever" @api.should be_valid_type(:mytype) end it "should not be valid unless it's a node, class, builtin type, or defined resource" do collection = stub 'collection' @api.stubs(:known_resource_types).returns collection collection.expects(:definition).returns nil Puppet::Type.expects(:type).returns nil @api.should_not be_valid_type(:mytype) end end describe "when creating a resource" do before do @api.scope.stubs(:source).returns stub("source") @api.scope.compiler.stubs(:add_resource) @created_resource = Puppet::Parser::Resource.new("yay", "eh", :scope => @api.scope) end it "should create and return a resource of the type specified" do Puppet::Parser::Resource.expects(:new).with { |type, title, args| type == "mytype" }.returns @created_resource @api.create_resource("mytype", "myname", {:foo => "bar"}).should == [@created_resource] end it "should use the name from the first element of the provided argument array" do Puppet::Parser::Resource.expects(:new).with { |type, title, args| title == "myname" }.returns @created_resource @api.create_resource("mytype", "myname", {:foo => "bar"}) end it "should create multiple resources if the first element of the argument array is an array" do second_resource = Puppet::Parser::Resource.new('yay', "eh", :scope => @api.scope) Puppet::Parser::Resource.expects(:new).with { |type, title, args| title == "first" }.returns @created_resource Puppet::Parser::Resource.expects(:new).with { |type, title, args| title == "second" }.returns @created_resource @api.create_resource("mytype", ["first", "second"], {:foo => "bar"}) end it "should provide its scope as the scope" do Puppet::Parser::Resource.expects(:new).with { |type, title, args| args[:scope] == @api.scope }.returns @created_resource @api.create_resource("mytype", "myname", {:foo => "bar"}) end it "should set each provided argument as a parameter on the created resource" do result = @api.create_resource("mytype", "myname", {"foo" => "bar", "biz" => "baz"}).shift result["foo"].should == "bar" result["biz"].should == "baz" end it "should add the resource to the scope's copmiler" do Puppet::Parser::Resource.expects(:new).returns @created_resource @api.scope.compiler.expects(:add_resource).with(@api.scope, @created_resource) @api.create_resource("mytype", "myname", {:foo => "bar"}) end it "should fail if the resource parameters are not a hash" do lambda { @api.create_resource("mytype", "myname", %w{foo bar}) }.should raise_error(ArgumentError) end end describe "when an unknown method is called" do it "should create a resource if the method name is a valid type" do @api.expects(:valid_type?).with(:mytype).returns true @api.expects(:create_resource).with(:mytype, "myname", {:foo => "bar"}).returns true @api.mytype("myname", :foo => "bar") end it "should call any function whose name matches the undefined method if the name is not a valid type" do @api.expects(:valid_type?).with(:myfunc).returns false @api.expects(:create_resource).never Puppet::Parser::Functions.expects(:function).with(:myfunc).returns true @api.expects(:call_function).with(:myfunc, %w{foo bar}) @api.myfunc("foo", "bar") end it "should raise a method missing error if the method is neither a type nor a function" do @api.expects(:valid_type?).with(:myfunc).returns false @api.expects(:create_resource).never Puppet::Parser::Functions.expects(:function).with(:myfunc).returns false @api.expects(:call_function).never lambda { @api.myfunc("foo", "bar") }.should raise_error(NoMethodError) end end it "should mark the specified resource as exported when creating a single exported resource" do resources = @api.export @api.file("/my/file", :ensure => :present) resources[0].should be_exported end it "should mark all created resources as exported when creating exported resources using a block" do @compiler.expects(:add_resource).with { |s, res| res.exported == true } @api.export { file "/my/file", :ensure => :present } end it "should mark the specified resource as virtual when creating a single virtual resource" do resources = @api.virtual @api.file("/my/file", :ensure => :present) resources[0].should be_virtual end it "should mark all created resources as virtual when creating virtual resources using a block" do @compiler.expects(:add_resource).with { |s, res| res.virtual == true } @api.virtual { file "/my/file", :ensure => :present } end end