summaryrefslogtreecommitdiffstats
path: root/spec/unit/parser/functions/create_resources_spec.rb
blob: 94b1e7c6840e82d2318a63c401247f4dee140afd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
require 'puppet'
require 'spec_helper'

describe 'function for dynamically creating resources' do

  def get_scope
    @topscope = Puppet::Parser::Scope.new
    # This is necessary so we don't try to use the compiler to discover our parent.
    @topscope.parent = nil
    @scope = Puppet::Parser::Scope.new
    @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
    @scope.parent = @topscope
    @compiler = @scope.compiler
  end
  before :each do
    get_scope
    Puppet::Parser::Functions.function(:create_resources)
  end

  it "should exist" do
    Puppet::Parser::Functions.function(:create_resources).should == "function_create_resources"
  end
  it 'should require two arguments' do
    lambda { @scope.function_create_resources(['foo']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2)')
  end
  describe 'when creating native types' do
    before :each do
      Puppet[:code]='notify{test:}'
      get_scope
      @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
    end
    it 'empty hash should not cause resources to be added' do
      @scope.function_create_resources(['file', {}])
      @compiler.catalog.resources.size == 1
    end
    it 'should be able to add' do
      @scope.function_create_resources(['file', {'/etc/foo'=>{'ensure'=>'present'}}])
      @compiler.catalog.resource(:file, "/etc/foo")['ensure'].should == 'present'
    end
    it 'should accept multiple types' do
      type_hash = {}
      type_hash['foo'] = {'message' => 'one'}
      type_hash['bar'] = {'message' => 'two'}
      @scope.function_create_resources(['notify', type_hash])
      @compiler.catalog.resource(:notify, "foo")['message'].should == 'one'
      @compiler.catalog.resource(:notify, "bar")['message'].should == 'two'
    end
    it 'should fail to add non-existing type' do
      lambda { @scope.function_create_resources(['foo', {}]) }.should raise_error(ArgumentError, 'could not create resource of unknown type foo')
    end
    it 'should be able to add edges' do
      @scope.function_create_resources(['notify', {'foo'=>{'require' => 'Notify[test]'}}])
      @scope.compiler.compile
      rg = @scope.compiler.catalog.to_ral.relationship_graph
      test  = rg.vertices.find { |v| v.title == 'test' }
      foo   = rg.vertices.find { |v| v.title == 'foo' }
      test.should be
      foo.should be
      rg.path_between(test,foo).should be
    end
  end
  describe 'when dynamically creating resource types' do
    before :each do 
      Puppet[:code]=
'define foo($one){notify{$name: message => $one}}
notify{test:}
'
      get_scope
      @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
      Puppet::Parser::Functions.function(:create_resources)
    end
    it 'should be able to create defined resoure types' do
      @scope.function_create_resources(['foo', {'blah'=>{'one'=>'two'}}])
      # still have to compile for this to work...
      # I am not sure if this constraint ruins the tests
      @scope.compiler.compile
      @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
    end
    it 'should fail if defines are missing params' do
      @scope.function_create_resources(['foo', {'blah'=>{}}])
      lambda { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /Must pass one to Foo\[blah\]/)
    end
    it 'should be able to add multiple defines' do
      hash = {}
      hash['blah'] = {'one' => 'two'}
      hash['blaz'] = {'one' => 'three'}
      @scope.function_create_resources(['foo', hash])
      # still have to compile for this to work...
      # I am not sure if this constraint ruins the tests
      @scope.compiler.compile
      @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
      @compiler.catalog.resource(:notify, "blaz")['message'].should == 'three'
    end
    it 'should be able to add edges' do
      @scope.function_create_resources(['foo', {'blah'=>{'one'=>'two', 'require' => 'Notify[test]'}}])
      @scope.compiler.compile
      rg = @scope.compiler.catalog.to_ral.relationship_graph
      test = rg.vertices.find { |v| v.title == 'test' }
      blah = rg.vertices.find { |v| v.title == 'blah' }
      test.should be
      blah.should be
      # (Yoda speak like we do)
      rg.path_between(test,blah).should be
      @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
    end
  end
  describe 'when creating classes' do
    before :each do
      Puppet[:code]=
'class bar($one){notify{test: message => $one}}
notify{tester:}
'
      get_scope
      @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
      Puppet::Parser::Functions.function(:create_resources)
    end
    it 'should be able to create classes', :'fails_on_ruby_1.9.2' => true do
      @scope.function_create_resources(['class', {'bar'=>{'one'=>'two'}}])
      @scope.compiler.compile
      @compiler.catalog.resource(:notify, "test")['message'].should == 'two'
      @compiler.catalog.resource(:class, "bar").should_not be_nil#['message'].should == 'two'
    end
    it 'should fail to create non-existing classes' do
      lambda { @scope.function_create_resources(['class', {'blah'=>{'one'=>'two'}}]) }.should raise_error(ArgumentError ,'could not find hostclass blah')
    end
    it 'should be able to add edges', :'fails_on_ruby_1.9.2' => true do
      @scope.function_create_resources(['class', {'bar'=>{'one'=>'two', 'require' => 'Notify[tester]'}}])
      @scope.compiler.compile
      rg = @scope.compiler.catalog.to_ral.relationship_graph
      test   = rg.vertices.find { |v| v.title == 'test' }
      tester = rg.vertices.find { |v| v.title == 'tester' }
      test.should be
      tester.should be
      rg.path_between(tester,test).should be
    end
  end
end