Module: RSpec::Puppet::Support

Included in:
ClassExampleGroup, DefineExampleGroup, FunctionExampleGroup, HostExampleGroup
Defined in:
lib/rspec-puppet/support.rb

Constant Summary collapse

@@cache =
{}

Instance Method Summary collapse

Instance Method Details

#build_catalog(*args) ⇒ Object



149
150
151
# File 'lib/rspec-puppet/support.rb', line 149

def build_catalog(*args)
  @@cache[args] ||= self.build_catalog_without_cache(*args)
end

#build_catalog_without_cache(nodename, facts_val, code) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/rspec-puppet/support.rb', line 128

def build_catalog_without_cache(nodename, facts_val, code)
  Puppet[:code] = code

  stub_facts! facts_val

  node_obj = Puppet::Node.new(nodename)

  node_obj.merge(facts_val)

  # trying to be compatible with 2.7 as well as 2.6
  if Puppet::Resource::Catalog.respond_to? :find
    Puppet::Resource::Catalog.find(node_obj.name, :use_node => node_obj)
  else
    Puppet::Resource::Catalog.indirection.find(node_obj.name, :use_node => node_obj)
  end
end

#build_node(name, opts = {}) ⇒ Object



180
181
182
183
184
# File 'lib/rspec-puppet/support.rb', line 180

def build_node(name, opts = {})
  node_environment = Puppet::Node::Environment.new('test')
  opts.merge!({:environment => node_environment})
  Puppet::Node.new(name, opts)
end

#catalogue(type) ⇒ Object



6
7
8
9
10
11
12
13
14
15
# File 'lib/rspec-puppet/support.rb', line 6

def catalogue(type)
  vardir = setup_puppet

  code = import_str + pre_cond + test_manifest(type)
  node_name = nodename(type)

  catalogue = build_catalog(node_name, facts_hash(node_name), code)
  FileUtils.rm_rf(vardir) if File.directory?(vardir)
  catalogue
end

#escape_special_chars(string) ⇒ Object



159
160
161
162
# File 'lib/rspec-puppet/support.rb', line 159

def escape_special_chars(string)
  string.gsub!(/\$/, "\\$")
  string
end

#facts_hash(node) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/rspec-puppet/support.rb', line 81

def facts_hash(node)
  facts_val = {
    'hostname' => node.split('.').first,
    'fqdn'     => node,
    'domain'   => node.split('.', 2).last,
  }

  if RSpec.configuration.default_facts.any?
    facts_val.merge!(munge_facts(RSpec.configuration.default_facts))
  end

  facts_val.merge!(munge_facts(facts)) if self.respond_to?(:facts)
  facts_val
end

#import_strObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rspec-puppet/support.rb', line 17

def import_str
  klass_name = self.class.top_level_description.downcase

  if File.exists?(File.join(Puppet[:modulepath], 'manifests', 'init.pp'))
    path_to_manifest = File.join([
      Puppet[:modulepath],
      'manifests',
      klass_name.split('::')[1..-1]
    ].flatten)
    import_str = [
      "import '#{Puppet[:modulepath]}/manifests/init.pp'",
      "import '#{path_to_manifest}.pp'",
      '',
    ].join("\n")
  elsif File.exists?(Puppet[:modulepath])
    import_str = "import '#{Puppet[:manifest]}'\n"
  else
    import_str = ""
  end

  import_str
end

#munge_facts(facts) ⇒ Object



153
154
155
156
157
# File 'lib/rspec-puppet/support.rb', line 153

def munge_facts(facts)
  output = {}
  facts.keys.each { |key| output[key.to_s] = facts[key] }
  output
end

#nodename(type) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/rspec-puppet/support.rb', line 60

def nodename(type)
  if [:class, :define, :function].include? type
    self.respond_to?(:node) ? node : Puppet[:certname]
  else
    self.class.top_level_description.downcase
  end
end

#param_strObject



96
97
98
99
100
101
# File 'lib/rspec-puppet/support.rb', line 96

def param_str
  params.keys.map do |r|
    param_val = escape_special_chars(params[r].inspect)
    "#{r.to_s} => #{param_val}"
  end.join(', ')
end

#pre_condObject



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rspec-puppet/support.rb', line 69

def pre_cond
  if self.respond_to?(:pre_condition) && !pre_condition.nil?
    if pre_condition.is_a? Array
      pre_condition.join("\n")
    else
      pre_condition
    end
  else
    ''
  end
end

#scope(compiler, node_name) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rspec-puppet/support.rb', line 164

def scope(compiler, node_name)
  if Puppet.version =~ /^2\.[67]/
    # loadall should only be necessary prior to 3.x
    # Please note, loadall needs to happen first when creating a scope, otherwise
    # you might receive undefined method `function_*' errors
    Puppet::Parser::Functions.autoloader.loadall
    scope = Puppet::Parser::Scope.new(:compiler => compiler)
  else
    scope = Puppet::Parser::Scope.new(compiler)
  end

  scope.source = Puppet::Resource::Type.new(:node, node_name)
  scope.parent = compiler.topscope
  scope
end

#setup_puppetObject



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rspec-puppet/support.rb', line 103

def setup_puppet
  vardir = Dir.mktmpdir
  Puppet[:vardir] = vardir

  [
    [:modulepath, :module_path],
    [:manifestdir, :manifest_dir],
    [:manifest, :manifest],
    [:templatedir, :template_dir],
    [:config, :config],
    [:confdir, :confdir],
    [:hiera_config, :hiera_config],
  ].each do |a, b|
    value = self.respond_to?(b) ? self.send(b) : RSpec.configuration.send(b)
    begin
      Puppet[a] = value
    rescue ArgumentError
      Puppet.settings.setdefaults(:main, {a => {:default => value, :desc => a.to_s}})
    end
  end

  Puppet[:libdir] = Dir["#{Puppet[:modulepath]}/*/lib"].entries.join(File::PATH_SEPARATOR)
  vardir
end

#stub_facts!(facts) ⇒ Object



145
146
147
# File 'lib/rspec-puppet/support.rb', line 145

def stub_facts!(facts)
  facts.each { |k, v| Facter.add(k) { setcode { v } } }
end

#test_manifest(type) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rspec-puppet/support.rb', line 40

def test_manifest(type)
  klass_name = self.class.top_level_description.downcase

  if type == :class
    if !self.respond_to?(:params) || params == {}
      "include #{klass_name}"
    else
      "class { '#{klass_name}': #{param_str} }"
    end
  elsif type == :define
    if self.respond_to? :params
      "#{klass_name} { '#{title}': #{param_str} }"
    else
      "#{klass_name} { '#{title}': }"
    end
  elsif type == :host
    ""
  end
end