pdk 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +71 -2
  3. data/lib/pdk/cli/convert.rb +7 -9
  4. data/lib/pdk/cli/new/class.rb +2 -1
  5. data/lib/pdk/cli/new/defined_type.rb +2 -1
  6. data/lib/pdk/cli/new/provider.rb +2 -1
  7. data/lib/pdk/cli/new/task.rb +2 -1
  8. data/lib/pdk/cli/new/test.rb +2 -1
  9. data/lib/pdk/cli/new/transport.rb +2 -1
  10. data/lib/pdk/cli/remove/config.rb +80 -0
  11. data/lib/pdk/cli/remove.rb +20 -0
  12. data/lib/pdk/cli/set/config.rb +119 -0
  13. data/lib/pdk/cli/set.rb +20 -0
  14. data/lib/pdk/cli/update.rb +6 -8
  15. data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
  16. data/lib/pdk/cli/util.rb +1 -0
  17. data/lib/pdk/cli.rb +2 -0
  18. data/lib/pdk/config.rb +96 -13
  19. data/lib/pdk/context.rb +8 -5
  20. data/lib/pdk/generate/defined_type.rb +25 -32
  21. data/lib/pdk/generate/module.rb +11 -10
  22. data/lib/pdk/generate/provider.rb +16 -65
  23. data/lib/pdk/generate/puppet_class.rb +25 -31
  24. data/lib/pdk/generate/puppet_object.rb +83 -187
  25. data/lib/pdk/generate/resource_api_object.rb +55 -0
  26. data/lib/pdk/generate/task.rb +28 -46
  27. data/lib/pdk/generate/transport.rb +21 -75
  28. data/lib/pdk/generate.rb +1 -0
  29. data/lib/pdk/module/convert.rb +41 -23
  30. data/lib/pdk/module/release.rb +1 -1
  31. data/lib/pdk/module/update.rb +6 -10
  32. data/lib/pdk/module/update_manager.rb +7 -0
  33. data/lib/pdk/module.rb +0 -1
  34. data/lib/pdk/template/fetcher/git.rb +85 -0
  35. data/lib/pdk/template/fetcher/local.rb +28 -0
  36. data/lib/pdk/template/fetcher.rb +98 -0
  37. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +116 -0
  38. data/lib/pdk/template/renderer/v1/renderer.rb +132 -0
  39. data/lib/pdk/template/renderer/v1/template_file.rb +102 -0
  40. data/lib/pdk/template/renderer/v1.rb +25 -0
  41. data/lib/pdk/template/renderer.rb +96 -0
  42. data/lib/pdk/template/template_dir.rb +67 -0
  43. data/lib/pdk/template.rb +59 -0
  44. data/lib/pdk/tests/unit.rb +5 -0
  45. data/lib/pdk/util/json_finder.rb +84 -0
  46. data/lib/pdk/util/puppet_strings.rb +3 -3
  47. data/lib/pdk/util/template_uri.rb +4 -6
  48. data/lib/pdk/util.rb +4 -35
  49. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
  50. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
  51. data/lib/pdk/validate/invokable_validator.rb +2 -3
  52. data/lib/pdk/validate/validator.rb +7 -0
  53. data/lib/pdk/validate/validator_group.rb +1 -0
  54. data/lib/pdk/validate.rb +17 -10
  55. data/lib/pdk/version.rb +1 -1
  56. data/lib/pdk.rb +1 -1
  57. data/locales/pdk.pot +356 -228
  58. metadata +33 -12
  59. data/lib/pdk/module/template_dir/base.rb +0 -268
  60. data/lib/pdk/module/template_dir/git.rb +0 -91
  61. data/lib/pdk/module/template_dir/local.rb +0 -21
  62. data/lib/pdk/module/template_dir.rb +0 -115
  63. data/lib/pdk/template_file.rb +0 -96
@@ -2,75 +2,26 @@ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Generate
5
- class Provider < PuppetObject
6
- OBJECT_TYPE = :provider
7
-
8
- # Prepares the data needed to render the new defined type template.
9
- #
10
- # @return [Hash{Symbol => Object}] a hash of information that will be
11
- # provided to the defined type and defined type spec templates during
12
- # rendering.
13
- def template_data
14
- data = {
15
- name: object_name,
16
- provider_class: Provider.class_name_from_object_name(object_name),
17
- }
18
-
19
- data
20
- end
21
-
22
- def raise_precondition_error(error)
23
- raise PDK::CLI::ExitWithError, _('%{error}: Creating a provider needs some local configuration in your module.' \
24
- ' Please follow the docs at https://puppet.com/docs/puppet/latest/create_types_and_providers_resource_api.html.') % { error: error }
25
- end
26
-
27
- def check_preconditions
28
- super
29
- # These preconditions can be removed once the pdk-templates are carrying the puppet-resource_api gem by default, and have switched
30
- # the default mock_with value.
31
- sync_path = PDK::Util.find_upwards('.sync.yml')
32
- if sync_path.nil?
33
- raise_precondition_error(_('.sync.yml not found'))
34
- end
35
- sync = YAML.load_file(sync_path)
36
- if !sync.is_a? Hash
37
- raise_precondition_error(_('.sync.yml contents is not a Hash'))
38
- elsif !sync.key? 'Gemfile'
39
- raise_precondition_error(_('Gemfile configuration not found'))
40
- elsif !sync['Gemfile'].key? 'optional'
41
- raise_precondition_error(_('Gemfile.optional configuration not found'))
42
- elsif !sync['Gemfile']['optional'].key? ':development'
43
- raise_precondition_error(_('Gemfile.optional.:development configuration not found'))
44
- elsif sync['Gemfile']['optional'][':development'].none? { |g| g['gem'] == 'puppet-resource_api' }
45
- raise_precondition_error(_('puppet-resource_api not found in the Gemfile config'))
46
- elsif !sync.key? 'spec/spec_helper.rb'
47
- raise_precondition_error(_('spec/spec_helper.rb configuration not found'))
48
- elsif !sync['spec/spec_helper.rb'].key? 'mock_with'
49
- raise_precondition_error(_('spec/spec_helper.rb.mock_with configuration not found'))
50
- elsif !sync['spec/spec_helper.rb']['mock_with'] == ':rspec'
51
- raise_precondition_error(_('spec/spec_helper.rb.mock_with not set to \':rspec\''))
52
- end
53
- end
54
-
55
- # @return [String] the path where the new provider will be written.
56
- def target_object_path
57
- @target_object_path ||= File.join(module_dir, 'lib', 'puppet', 'provider', object_name, object_name) + '.rb'
5
+ class Provider < ResourceAPIObject
6
+ def friendly_name
7
+ 'Resource API Provider'.freeze
58
8
  end
59
9
 
60
- # @return [String] the path where the new type will be written.
61
- def target_type_path
62
- @target_type_path ||= File.join(module_dir, 'lib', 'puppet', 'type', object_name) + '.rb'
63
- end
64
-
65
- # @return [String] the path where the tests for the new provider
66
- # will be written.
67
- def target_spec_path
68
- @target_spec_path ||= File.join(module_dir, 'spec', 'unit', 'puppet', 'provider', object_name, object_name) + '_spec.rb'
10
+ def template_files
11
+ files = {
12
+ 'provider_spec.erb' => File.join('spec', 'unit', 'puppet', 'provider', object_name, object_name) + '_spec.rb',
13
+ 'provider_type_spec.erb' => File.join('spec', 'unit', 'puppet', 'type', object_name) + '_spec.rb',
14
+ }
15
+ return files if spec_only?
16
+ files.merge(
17
+ 'provider.erb' => File.join('lib', 'puppet', 'provider', object_name, object_name) + '.rb',
18
+ 'provider_type.erb' => File.join('lib', 'puppet', 'type', object_name) + '.rb',
19
+ )
69
20
  end
70
21
 
71
- # @return [String] the path where the tests for the new type will be written.
72
- def target_type_spec_path
73
- @target_type_spec_path ||= File.join(module_dir, 'spec', 'unit', 'puppet', 'type', object_name) + '_spec.rb'
22
+ def template_data
23
+ { name: object_name,
24
+ provider_class: class_name_from_object_name(object_name) }
74
25
  end
75
26
  end
76
27
  end
@@ -3,46 +3,40 @@ require 'pdk'
3
3
  module PDK
4
4
  module Generate
5
5
  class PuppetClass < PuppetObject
6
- OBJECT_TYPE = :class
7
6
  PUPPET_STRINGS_TYPE = 'puppet_classes'.freeze
8
7
 
9
- # Prepares the data needed to render the new Puppet class template.
10
- #
11
- # @return [Hash{Symbol => Object}] a hash of information that will be
12
- # provided to the class and class spec templates during rendering.
13
- def template_data
14
- data = { name: object_name }
8
+ def initialize(*_args)
9
+ super
10
+ object_name_parts = @object_name.split('::')
15
11
 
16
- data
12
+ @object_name = if object_name_parts.first == module_name
13
+ object_name
14
+ else
15
+ [module_name, object_name].join('::')
16
+ end
17
17
  end
18
18
 
19
- # Calculates the path to the .pp file that the new class will be written
20
- # to.
21
- #
22
- # @return [String] the path where the new class will be written.
23
- def target_object_path
24
- @target_pp_path ||= begin
25
- class_name_parts = object_name.split('::')[1..-1]
26
- class_name_parts << 'init' if class_name_parts.empty?
27
-
28
- "#{File.join(module_dir, 'manifests', *class_name_parts)}.pp"
29
- end
19
+ def friendly_name
20
+ 'Puppet Class'.freeze
30
21
  end
31
22
 
32
- # Calculates the path to the file where the tests for the new class will
33
- # be written.
34
- #
35
- # @return [String] the path where the tests for the new class will be
36
- # written.
37
- def target_spec_path
38
- @target_spec_path ||= begin
39
- class_name_parts = object_name.split('::')
23
+ def template_files
24
+ # Calculate the class tests name
25
+ class_name_parts = object_name.split('::')
26
+ # Drop the module name if the object name contains multiple parts
27
+ class_name_parts.delete_at(0) if class_name_parts.length > 1
28
+ files = { 'class_spec.erb' => File.join('spec', 'classes', *class_name_parts) + '_spec.rb' }
29
+ return files if spec_only?
30
+
31
+ class_name_parts = object_name.split('::')[1..-1]
32
+ class_name_parts << 'init' if class_name_parts.empty?
33
+ files['class.erb'] = File.join('manifests', *class_name_parts) + '.pp'
40
34
 
41
- # drop the module name if the object name contains multiple parts
42
- class_name_parts.delete_at(0) if class_name_parts.length > 1
35
+ files
36
+ end
43
37
 
44
- "#{File.join(module_dir, 'spec', 'classes', *class_name_parts)}_spec.rb"
45
- end
38
+ def template_data
39
+ { name: object_name }
46
40
  end
47
41
  end
48
42
  end
@@ -3,7 +3,7 @@ require 'pdk'
3
3
  module PDK
4
4
  module Generate
5
5
  class PuppetObject
6
- attr_reader :module_dir
6
+ attr_reader :context
7
7
  attr_reader :object_name
8
8
  attr_reader :options
9
9
 
@@ -20,228 +20,124 @@ module PDK
20
20
  # will contain the object.
21
21
  # @param object_name [String] The name of the object.
22
22
  # @param options [Hash{Symbol => Object}]
23
- #
24
- # @api public
25
- def initialize(module_dir, object_name, options)
26
- @module_dir = module_dir
23
+ def initialize(context, object_name, options)
24
+ raise ArgumentError, _('Expected PDK::Context::AbstractContext but got \'%{klass}\' for context') % { klass: context.class } unless context.is_a?(PDK::Context::AbstractContext)
25
+ @context = context
27
26
  @options = options
28
27
  @object_name = object_name
29
-
30
- if [:class, :defined_type].include?(object_type) # rubocop:disable Style/GuardClause
31
- object_name_parts = object_name.split('::')
32
-
33
- @object_name = if object_name_parts.first == module_name
34
- object_name
35
- else
36
- [module_name, object_name].join('::')
37
- end
38
- end
39
28
  end
40
29
 
30
+ # Whether the generator should only return test (spec) files
31
+ # @return [Boolean]
41
32
  def spec_only?
42
33
  @options[:spec_only]
43
34
  end
44
35
 
45
- # @abstract Subclass and implement {#template_data} to provide data to
46
- # the templates during rendering. Implementations of this method should
47
- # return a Hash!{Symbol => Object}.
48
- def template_data
36
+ # Subclass and implement {#friendly_name} to provide a nice name to show users in CLI
37
+ # @abstract
38
+ # @return String
39
+ def friendly_name
49
40
  raise NotImplementedError
50
41
  end
51
42
 
52
- # @abstract Subclass and implement {#target_object_path}. Implementations
53
- # of this method should return a String containing the destination path
54
- # of the object being generated.
55
- def target_object_path
43
+ # Subclass and implement {#template_files} to provide the template files to
44
+ # render. Implementations of this method should return a Hash!{String => String}.
45
+ # @abstract
46
+ # @return Hash{String => String} Hash key is the source template file and the Hash value is
47
+ # the relative destination path
48
+ def template_files
56
49
  raise NotImplementedError
57
50
  end
58
51
 
59
- # @abstract Subclass and implement {#target_type_path}. Implementations
60
- # of this method should return a String containing the destination path
61
- # of the additional object file being generated.
62
- # @return [String] returns nil if there is no additional object file
63
- def target_type_path
64
- nil
65
- end
66
-
67
- # @abstract Subclass and implement {#target_spec_path}. Implementations
68
- # of this method should return a String containing the destination path
69
- # of the tests for the object being generated.
70
- def target_spec_path
52
+ # Subclass and implement {#template_data} to provide data to the templates during rendering.
53
+ # @abstract
54
+ # @return Hash{Symbol => Object}
55
+ def template_data
71
56
  raise NotImplementedError
72
57
  end
73
58
 
74
- # @abstract Subclass and implement {#target_type_spec_path}. Implementations
75
- # of this method should return a String containing the destination path
76
- # of the tests for the object being generated.
77
- def target_type_spec_path
78
- nil
79
- end
80
-
81
- # @abstract Subclass and implement {#target_device_path}. Implementations
82
- # of this method should return a String containing the destination path
83
- # of the device class being generated.
84
- def target_device_path
85
- nil
86
- end
87
-
88
- # Retrieves the type of the object being generated, e.g. :class,
89
- # :defined_type, etc. This is specified in the subclass' OBJECT_TYPE
90
- # constant.
59
+ # Raises an error if any pre-conditions are not met
91
60
  #
92
- # @return [Symbol] the type of the object being generated.
93
- #
94
- # @api private
95
- def object_type
96
- self.class::OBJECT_TYPE
61
+ # @return [void]
62
+ # @abstract
63
+ def check_preconditions
64
+ raise ArgumentError, _('Expected a module context but got %{context_name}') % { context_name: context.display_name } unless context.is_a?(PDK::Context::Module)
97
65
  end
98
66
 
99
- # Retrieves the type of the object being generated as represented in
100
- # the JSON output of puppet-strings.
67
+ # Check the preconditions of this template group, behaving as a predicate rather than raising an exception.
101
68
  #
102
- # @return [String] the type of the object being generated or nil if
103
- # there is no mapping.
104
- #
105
- # @api private
106
- def self.puppet_strings_type
107
- return nil unless const_defined?(:PUPPET_STRINGS_TYPE)
108
-
109
- self::PUPPET_STRINGS_TYPE
69
+ # @return [Boolean] true if the generator is safe to run, otherwise false.
70
+ def can_run?
71
+ check_preconditions
72
+ true
73
+ rescue StandardError
74
+ false
110
75
  end
111
76
 
112
- # Returns an array of possible target path strings.
113
- def targets
114
- targets = [
115
- target_spec_path,
116
- target_type_spec_path,
117
- ]
118
-
119
- unless spec_only?
120
- targets += [
121
- target_object_path,
122
- target_type_path,
123
- target_device_path,
124
- ]
125
- end
126
-
127
- targets.compact
77
+ # Creates an instance of an update manager
78
+ # @api private
79
+ def update_manager_instance
80
+ require 'pdk/module/update_manager'
81
+ PDK::Module::UpdateManager.new
128
82
  end
129
83
 
130
- # Check preconditions of this template group. By default this only makes sure that the target files do not
131
- # already exist. Override this (and call super) to add your own preconditions.
132
- #
133
- # @raise [PDK::CLI::ExitWithError] if the target files already exist.
84
+ # Stages and then executes the changes for the templates to be rendereed.
85
+ # This is the main entry point for the class.
134
86
  #
87
+ # @see #stage_changes
88
+ # @return [PDK::Module::UpdateManager] The update manager which implemented the changes
135
89
  # @api public
136
- def check_preconditions
137
- require 'pdk/util/filesystem'
138
-
139
- targets.each do |target_file|
140
- next unless PDK::Util::Filesystem.exist?(target_file)
141
-
142
- raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % {
143
- file: target_file,
144
- object_type: spec_only? ? 'unit test' : object_type,
145
- }
146
- end
147
- end
148
-
149
- # Check the preconditions of this template group, behaving as a
150
- # predicate rather than raising an exception.
151
- #
152
- # @return [Boolean] true if the generator is safe to run, otherwise
153
- # false.
154
- def can_run?
155
- check_preconditions
156
- true
157
- rescue PDK::CLI::ExitWithError
158
- false
90
+ def run(update_manager = update_manager_instance)
91
+ stage_changes(update_manager).sync_changes!
92
+ update_manager
159
93
  end
160
94
 
161
95
  # Check that the templates can be rendered. Find an appropriate template
162
- # and create the target files from the template. This is the main entry
96
+ # and stages the target files from the template. This is the main entry
163
97
  # point for the class.
164
98
  #
165
99
  # @raise [PDK::CLI::ExitWithError] if the target files already exist.
166
100
  # @raise [PDK::CLI::FatalError] (see #render_file)
167
- #
101
+ # @return [PDK::Module::UpdateManager] The update manager with the staged changes
168
102
  # @api public
169
- def run
103
+ def stage_changes(update_manager)
170
104
  check_preconditions
171
105
 
172
- with_templates do |template_path, config_hash|
173
- data = template_data.merge(configs: config_hash)
106
+ with_templates do |template_dir|
107
+ template_files.each do |source_file, relative_dest_path|
108
+ new_content = template_dir.render_single_item(source_file, template_data)
109
+ next if new_content.nil?
174
110
 
175
- render_file(target_object_path, template_path[:object], data) unless spec_only?
176
- render_file(target_type_path, template_path[:type], data) if template_path[:type]
177
- render_file(target_device_path, template_path[:device], data) if template_path[:device]
178
- render_file(target_spec_path, template_path[:spec], data) if template_path[:spec]
179
- render_file(target_type_spec_path, template_path[:type_spec], data) if template_path[:type_spec]
111
+ stage_change(relative_dest_path, new_content, update_manager)
112
+ end
180
113
  end
114
+ non_template_files.each { |relative_dest_path, content| stage_change(relative_dest_path, content, update_manager) }
115
+
116
+ update_manager
181
117
  end
182
118
 
183
- # Render a file using the provided template and write it to disk.
184
- #
185
- # @param dest_path [String] The path that the rendered file should be
186
- # written to. Any necessary directories will be automatically created.
187
- # @param template_path [String] The path on disk to the file containing
188
- # the template.
189
- # @param data [Hash{Object => Object}] The data to be provided to the
190
- # template when rendering.
191
- #
192
- # @raise [PDK::CLI::FatalError] if the parent directories to `dest_path`
193
- # do not exist and could not be created.
194
- # @raise [PDK::CLI::FatalError] if the rendered file could not be written
195
- # to `dest_path`.
196
- #
119
+ # Stages a single file into the Update Manager.
197
120
  # @return [void]
198
- #
199
121
  # @api private
200
- def render_file(dest_path, template_path, data)
201
- require 'pdk/template_file'
202
-
203
- write_file(dest_path) do
204
- PDK::TemplateFile.new(template_path, data).render
122
+ def stage_change(relative_dest_path, content, update_manager)
123
+ absolute_file_path = File.join(context.root_path, relative_dest_path)
124
+ if PDK::Util::Filesystem.exist?(absolute_file_path)
125
+ raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % {
126
+ file: absolute_file_path,
127
+ object_type: spec_only? ? 'unit test' : friendly_name,
128
+ }
205
129
  end
130
+ update_manager.add_file(absolute_file_path, content)
206
131
  end
207
132
 
208
- # Write the result of the block to disk.
209
- #
210
- # @param dest_path [String] The path that the rendered file should be
211
- # written to. Any necessary directories will be automatically created.
212
- # @param &block [String] The content to be written
213
- #
214
- # @raise [PDK::CLI::FatalError] if the parent directories to `dest_path`
215
- # do not exist and could not be created.
216
- # @raise [PDK::CLI::FatalError] if the rendered file could not be written
217
- # to `dest_path`.
218
- #
219
- # @return [void]
133
+ # A subclass may wish to stage files into the Update Manager, but the content is not templated. Subclasses
134
+ # can override this method to stage arbitrary files
220
135
  #
221
136
  # @api private
222
- def write_file(dest_path)
223
- require 'pdk/logger'
224
- require 'pdk/util/filesystem'
225
-
226
- PDK.logger.info(_("Creating '%{file}' from template.") % { file: dest_path })
227
-
228
- file_content = yield
229
-
230
- begin
231
- PDK::Util::Filesystem.mkdir_p(File.dirname(dest_path))
232
- rescue SystemCallError => e
233
- raise PDK::CLI::FatalError, _("Unable to create directory '%{path}': %{message}") % {
234
- path: File.dirname(dest_path),
235
- message: e.message,
236
- }
237
- end
238
-
239
- PDK::Util::Filesystem.write_file(dest_path, file_content)
240
- rescue SystemCallError => e
241
- raise PDK::CLI::FatalError, _("Unable to write to file '%{path}': %{message}") % {
242
- path: dest_path,
243
- message: e.message,
244
- }
137
+ # @return [Hash{String => String}] A Hash with the relative file path as the key and the new file content as the value.
138
+ # @abstract
139
+ def non_template_files
140
+ {}
245
141
  end
246
142
 
247
143
  # Search the possible template directories in order of preference to find
@@ -268,18 +164,15 @@ module PDK
268
164
  next
269
165
  end
270
166
 
271
- PDK::Module::TemplateDir.with(PDK::Util::TemplateURI.new(template[:uri])) do |template_dir|
272
- template_paths = template_dir.object_template_for(object_type)
273
-
274
- if template_paths
275
- config_hash = template_dir.object_config
276
- yield template_paths, config_hash
167
+ PDK::Template.with(PDK::Util::TemplateURI.new(template[:uri]), context) do |template_dir|
168
+ if template_files.any? { |source_file, _| template_dir.has_single_item?(source_file) }
169
+ yield template_dir
277
170
  # TODO: refactor to a search-and-execute form instead
278
171
  return # work is done # rubocop:disable Lint/NonLocalExitFromIterator
279
172
  elsif template[:allow_fallback]
280
- PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: object_type, url: template[:uri] })
173
+ PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: friendly_name, url: template[:uri] })
281
174
  else
282
- raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: object_type, url: template[:uri] }
175
+ raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: friendly_name, url: template[:uri] }
283
176
  end
284
177
  end
285
178
  end
@@ -320,15 +213,18 @@ module PDK
320
213
  #
321
214
  # @api private
322
215
  def module_name
323
- require 'pdk/util'
216
+ return nil unless context.is_a?(PDK::Context::Module)
324
217
 
325
- @module_name ||= PDK::Util.module_metadata['name'].rpartition('-').last
218
+ require 'pdk/util'
219
+ @module_name ||= PDK::Util.module_metadata(context.root_path)['name'].rpartition('-').last
326
220
  rescue ArgumentError => e
327
221
  raise PDK::CLI::FatalError, e
328
222
  end
329
223
 
330
- # transform a object name into a ruby class name
331
- def self.class_name_from_object_name(object_name)
224
+ private
225
+
226
+ # Transform an object name into a ruby class name
227
+ def class_name_from_object_name(object_name)
332
228
  object_name.to_s.split('_').map(&:capitalize).join
333
229
  end
334
230
  end
@@ -0,0 +1,55 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Generate
5
+ # An abstract class for generated objects that require the Puppet Resource API Gem
6
+ #
7
+ # @abstract
8
+ class ResourceAPIObject < PuppetObject
9
+ #:nocov: This is tested in spec/acceptance/new_transport_spec.rb
10
+ # @see PDK::Generate::PuppetObject.check_preconditions
11
+ def check_preconditions
12
+ super
13
+ # Note that these preconditions are only applicable to the current (V1) template rendering layout and will need to be changed
14
+ # when additional template renderers are introduced.
15
+ #
16
+ # These preconditions can be removed once the pdk-templates are carrying the puppet-resource_api gem by default, and have switched
17
+ # the default mock_with value.
18
+ sync_path = PDK::Util.find_upwards('.sync.yml')
19
+ if sync_path.nil?
20
+ raise_precondition_error(_('.sync.yml not found'))
21
+ end
22
+ sync = YAML.load_file(sync_path)
23
+ if !sync.is_a? Hash
24
+ raise_precondition_error(_('.sync.yml contents is not a Hash'))
25
+ elsif !sync.key? 'Gemfile'
26
+ raise_precondition_error(_('Gemfile configuration not found'))
27
+ elsif !sync['Gemfile'].key? 'optional'
28
+ raise_precondition_error(_('Gemfile.optional configuration not found'))
29
+ elsif !sync['Gemfile']['optional'].key? ':development'
30
+ raise_precondition_error(_('Gemfile.optional.:development configuration not found'))
31
+ elsif sync['Gemfile']['optional'][':development'].none? { |g| g['gem'] == 'puppet-resource_api' }
32
+ raise_precondition_error(_('puppet-resource_api not found in the Gemfile config'))
33
+ elsif !sync.key? 'spec/spec_helper.rb'
34
+ raise_precondition_error(_('spec/spec_helper.rb configuration not found'))
35
+ elsif !sync['spec/spec_helper.rb'].key? 'mock_with'
36
+ raise_precondition_error(_('spec/spec_helper.rb.mock_with configuration not found'))
37
+ elsif !sync['spec/spec_helper.rb']['mock_with'] == ':rspec'
38
+ raise_precondition_error(_('spec/spec_helper.rb.mock_with not set to \':rspec\''))
39
+ end
40
+ end
41
+
42
+ # Helper method to raise an error if the Resource API is not available
43
+ #
44
+ # @api private
45
+ def raise_precondition_error(error)
46
+ raise PDK::CLI::ExitWithError, _('%{error}: Creating a %{thing_name} needs some local configuration in your module.' \
47
+ ' Please follow the docs at https://puppet.com/docs/puppet/latest/create_types_and_providers_resource_api.html') % {
48
+ thing_name: friendly_name,
49
+ error: error,
50
+ }
51
+ end
52
+ #:nocov:
53
+ end
54
+ end
55
+ end