Class: Retrospec::Puppet::Generators::FunctionGenerator

Inherits:
Retrospec::Plugins::V1::Plugin
  • Object
show all
Defined in:
lib/retrospec/plugins/v1/plugin/generators/function_generator.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(module_path, spec_object = {}) ⇒ FunctionGenerator

retrospec will initilalize this class so its up to you to set any additional variables you need to get the job done.



10
11
12
13
14
15
16
17
18
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 10

def initialize(module_path, spec_object = {})
  super
  # below is the Spec Object which serves as a context for template rendering
  # you will need to initialize this object, so the erb templates can get the binding
  # the SpecObject can be customized to your liking as its different for every plugin gem.
  @context = OpenStruct.new({ :name => spec_object[:name], :return_type => spec_object[:return_type],
                            :function_type => spec_object[:type],
                            :test_type => spec_object[:test_type] }.merge(spec_object))
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



7
8
9
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 7

def context
  @context
end

#template_dirObject (readonly)

Puppet currently has two versions of functions (v3, v4). At the time of writing v4 is still new and not used very much. Because of this we will want to allow the user to pick which version of puppet function dsl they wish to use. Based on the version, a slightly different template will be rendered. This method will return the template dir based on the version passed in. By default this method looks inside the user supplied template dir for existence of a template and if true returns that base path, if false returns the template directory inside the gem location which is mainly used for development only.



26
27
28
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 26

def template_dir
  @template_dir
end

Class Method Details

.run_cli(global_opts, args = ARGV) ⇒ Object

used to display subcommand options to the cli the global options are passed in for your usage optimist.rubyforge.org all options here are available in the config passed into config object returns the parameters



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
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 51

def self.run_cli(global_opts, args=ARGV)
  func_types = %w(v3 v4 native)
  func_type  = global_opts['plugins::puppet::default_function_version'] || 'v4'
  test_type  = global_opts['plugins::puppet::default_function_test_type'] || 'rspec'
  sub_command_opts = Optimist.options(args) do
    banner <<-EOS
Generates a new function with the given name.

    EOS
    opt :name, 'The name of the function you wish to create', :type => :string, :required => true, :short => '-n'
    opt :type, "The version type of the function (#{func_types.join(',')})", :type => :string, :required => false, :short => '-t',
        :default => func_type
    opt :test_type, 'The type of test file to create (rspec, ruby)', :default => test_type, :type => :string, :short => '-u'
    opt :return_type, 'The return type of the function (rvalue, statement)', :type => :string, :required => false,
        :short => '-r', :default => 'rvalue'
  end

  unless func_types.include? sub_command_opts[:type].downcase
    puts "Invalid type, must be one of #{func_types.join(',')}"
    Optimist.educate
    exit 1
  end
  unless sub_command_opts[:name]
    Optimist.educate
    exit 1
  end
  plugin_data = global_opts.merge(sub_command_opts)
  plugin_data
end

Instance Method Details

#discovered_functionsArray

Returns an array of functions found in either the v3,v4, native directories.

Returns:

  • (Array)

    an array of functions found in either the v3,v4, native directories



172
173
174
175
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 172

def discovered_functions
  Dir.glob([File.join(v3_function_dir, '*.rb'),
            File.join(v4_function_dir, '*.rb'), File.join(native_function_dir, '*.pp')]).sort
end

#function_dirObject

returns the function directory to create the the function in



82
83
84
85
86
87
88
89
90
91
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 82

def function_dir
  case function_type
  when 'v3'
    v3_function_dir
  when 'v4'
    v4_function_dir
  when 'native'
    native_function_dir
  end
end

#function_extObject



113
114
115
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 113

def function_ext
  function_type == 'native' ? '.pp' : '.rb'
end

#function_file_pathObject



122
123
124
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 122

def function_file_path
  File.join(template_dir, "function_template#{function_ext}.retrospec.erb")
end

#function_nameObject

returns the name of the function



118
119
120
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 118

def function_name
  context.name.gsub('::', '_')
end

#function_pathObject

returns the path to the function using the function directory



108
109
110
111
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 108

def function_path
  path = File.join(function_dir, function_name.to_s)
  path + function_ext
end

#function_typeObject

returns v3,v4, native to specify the function type



42
43
44
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 42

def function_type
  context.function_type
end

#generate_function_file(template = nil) ⇒ Object

generates the function file based on the template and context



127
128
129
130
131
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 127

def generate_function_file(template = nil)
  template ||= function_file_path
  safe_create_template_file(function_path, template, context)
  function_path
end

#generate_spec_filesObject

creates the spec files for the discovered_functions



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 211

def generate_spec_files
  spec_files = []
  discovered_functions.each do |file|
    begin
      if v3_function?(file)
        context.function_type = 'v3'
        file_data = Retrospec::Puppet::Parser::Functions.load_function(file)
      elsif native_function?(file)
        context.test_type = 'rspec'
        context.function_type = 'native'
        file_data = Parsers::NativeFunction.load_function(file)
      else
        context.function_type = 'v4'
        file_data = Retrospec::Puppet::Functions.load_function(file)
      end
    rescue NoMethodError => e
      puts "Error evaluating function for #{file}, skipping".warning
      next
    rescue SyntaxError => e
      puts "Function syntax is bad for #{file}, skipping".warning
      next  # lets skip functions that have bad syntax
    end
    # separate out namespace for v4 and native functions
    # TODO should we create sub directories for triple namespace functions one::two::three?
    file_name = file_data.name.to_s.split('::').last
    spec_path = File.join(spec_file_dir, "#{file_name}_spec.rb")
    spec_files << spec_path
    safe_create_template_file(spec_path, File.join(template_dir, template_file), file_data)
  end
  spec_files
end

#main_class_nameString

Returns - returns the main class name by reading the init.pp file.

Returns:

  • (String)
    • returns the main class name by reading the init.pp file



37
38
39
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 37

def main_class_name
  File.read(File.join(module_path, 'manifests', 'init.pp')).scan(/\s*class\s(\w+)/).flatten.first || ''
end

#namespaced_nameString

Returns - returns the namespaced function name ie. stdlib::round.

Returns:

  • (String)
    • returns the namespaced function name ie. stdlib::round



185
186
187
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 185

def namespaced_name
  [main_class_name, function_name].join('::')
end

#native_function?(function_file) ⇒ Boolean

Returns true if the function file is a native function.

Returns:

  • (Boolean)

    true if the function file is a native function



178
179
180
181
182
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 178

def native_function?(function_file)
  # mod_name/functions
  File.basename(Pathname.new(function_file).parent) == 'functions' &&
    File.extname(function_file) == '.pp'
end

#native_function_dirObject



103
104
105
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 103

def native_function_dir
  @native_function_dir || File.join(module_path, 'functions')
end

#native_spec_dirObject



147
148
149
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 147

def native_spec_dir
  File.join(module_path, 'spec', 'functions')
end

#spec_file_dirObject

returns the path to the spec directory because this can vary between test types and function types there are many supporting functions to determine which directory to use



136
137
138
139
140
141
142
143
144
145
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 136

def spec_file_dir
  case function_type
  when 'v3'
    v3_spec_dir
  when 'v4'
    v4_spec_dir
  when 'native'
    native_spec_dir
  end
end

#template_fileObject

returns the template file name based on the test type



202
203
204
205
206
207
208
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 202

def template_file
  if context.test_type == 'rspec'
    'function_rspec_template.retrospec.erb'
  else
    'function_ruby_template.retrospec.erb'
  end
end

#v3_function?(function_file) ⇒ Boolean

Returns true if the function file is a v3 function.

Returns:

  • (Boolean)

    true if the function file is a v3 function



196
197
198
199
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 196

def v3_function?(function_file)
  # mod_name/lib/puppet/parser/functions
  File.basename(Pathname.new(function_file).parent.parent) == 'parser'
end

#v3_function_dirObject

returns the path to the v3 function directory



94
95
96
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 94

def v3_function_dir
  @v3_function_dir || File.join(module_path, 'lib', 'puppet', 'parser', 'functions')
end

#v3_spec_dirObject

returns the path to the v3 spec directory if using using rspec test type the spec/functions is returned



153
154
155
156
157
158
159
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 153

def v3_spec_dir
  if context.test_type == 'ruby'
    File.join(module_path, 'spec', 'unit', 'puppet', 'parser', 'functions')
  else
    File.join(module_path, 'spec', 'functions')
  end
end

#v4_function?(function_file) ⇒ Boolean

Returns true if the function file is a v4 function.

Returns:

  • (Boolean)

    true if the function file is a v4 function



190
191
192
193
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 190

def v4_function?(function_file)
  # mod_name/lib/puppet/functions
  File.basename(Pathname.new(function_file).parent.parent) == 'functions'
end

#v4_function_dirObject

returns the path to the v4 function directory



99
100
101
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 99

def v4_function_dir
  @v4_function_dir || File.join(module_path, 'lib', 'puppet', 'functions')
end

#v4_spec_dirObject

returns the path to the v4 spec directory if using using rspec test type the spec/functions is returned



163
164
165
166
167
168
169
# File 'lib/retrospec/plugins/v1/plugin/generators/function_generator.rb', line 163

def v4_spec_dir
  if context.test_type == 'ruby'
    File.join(module_path, 'spec', 'unit', 'puppet', 'functions')
  else
    File.join(module_path, 'spec', 'functions')
  end
end