pdk 1.9.0 → 3.2.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 (163) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +744 -711
  3. data/README.md +23 -21
  4. data/lib/pdk/answer_file.rb +3 -112
  5. data/lib/pdk/bolt.rb +20 -0
  6. data/lib/pdk/cli/build.rb +51 -54
  7. data/lib/pdk/cli/bundle.rb +33 -29
  8. data/lib/pdk/cli/console.rb +148 -0
  9. data/lib/pdk/cli/convert.rb +46 -37
  10. data/lib/pdk/cli/env.rb +51 -0
  11. data/lib/pdk/cli/errors.rb +4 -3
  12. data/lib/pdk/cli/exec/command.rb +285 -0
  13. data/lib/pdk/cli/exec/interactive_command.rb +109 -0
  14. data/lib/pdk/cli/exec.rb +32 -201
  15. data/lib/pdk/cli/exec_group.rb +79 -43
  16. data/lib/pdk/cli/get/config.rb +26 -0
  17. data/lib/pdk/cli/get.rb +22 -0
  18. data/lib/pdk/cli/new/class.rb +20 -22
  19. data/lib/pdk/cli/new/defined_type.rb +21 -21
  20. data/lib/pdk/cli/new/fact.rb +27 -0
  21. data/lib/pdk/cli/new/function.rb +27 -0
  22. data/lib/pdk/cli/new/module.rb +40 -29
  23. data/lib/pdk/cli/new/provider.rb +18 -18
  24. data/lib/pdk/cli/new/task.rb +23 -22
  25. data/lib/pdk/cli/new/test.rb +52 -0
  26. data/lib/pdk/cli/new/transport.rb +27 -0
  27. data/lib/pdk/cli/new.rb +15 -9
  28. data/lib/pdk/cli/release/prep.rb +39 -0
  29. data/lib/pdk/cli/release/publish.rb +46 -0
  30. data/lib/pdk/cli/release.rb +185 -0
  31. data/lib/pdk/cli/remove/config.rb +83 -0
  32. data/lib/pdk/cli/remove.rb +22 -0
  33. data/lib/pdk/cli/set/config.rb +121 -0
  34. data/lib/pdk/cli/set.rb +22 -0
  35. data/lib/pdk/cli/test/unit.rb +71 -69
  36. data/lib/pdk/cli/test.rb +9 -8
  37. data/lib/pdk/cli/update.rb +38 -21
  38. data/lib/pdk/cli/util/command_redirector.rb +13 -3
  39. data/lib/pdk/cli/util/interview.rb +25 -9
  40. data/lib/pdk/cli/util/option_normalizer.rb +6 -6
  41. data/lib/pdk/cli/util/option_validator.rb +19 -9
  42. data/lib/pdk/cli/util/spinner.rb +13 -0
  43. data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
  44. data/lib/pdk/cli/util.rb +105 -48
  45. data/lib/pdk/cli/validate.rb +96 -111
  46. data/lib/pdk/cli.rb +134 -87
  47. data/lib/pdk/config/errors.rb +5 -0
  48. data/lib/pdk/config/ini_file.rb +184 -0
  49. data/lib/pdk/config/ini_file_setting.rb +35 -0
  50. data/lib/pdk/config/json.rb +35 -0
  51. data/lib/pdk/config/json_schema_namespace.rb +137 -0
  52. data/lib/pdk/config/json_schema_setting.rb +51 -0
  53. data/lib/pdk/config/json_with_schema.rb +47 -0
  54. data/lib/pdk/config/namespace.rb +362 -0
  55. data/lib/pdk/config/setting.rb +134 -0
  56. data/lib/pdk/config/task_schema.json +116 -0
  57. data/lib/pdk/config/validator.rb +31 -0
  58. data/lib/pdk/config/yaml.rb +41 -0
  59. data/lib/pdk/config/yaml_with_schema.rb +51 -0
  60. data/lib/pdk/config.rb +304 -0
  61. data/lib/pdk/context/control_repo.rb +61 -0
  62. data/lib/pdk/context/module.rb +28 -0
  63. data/lib/pdk/context/none.rb +22 -0
  64. data/lib/pdk/context.rb +98 -0
  65. data/lib/pdk/control_repo.rb +89 -0
  66. data/lib/pdk/generate/defined_type.rb +27 -33
  67. data/lib/pdk/generate/fact.rb +26 -0
  68. data/lib/pdk/generate/function.rb +49 -0
  69. data/lib/pdk/generate/module.rb +160 -153
  70. data/lib/pdk/generate/provider.rb +16 -69
  71. data/lib/pdk/generate/puppet_class.rb +27 -32
  72. data/lib/pdk/generate/puppet_object.rb +100 -159
  73. data/lib/pdk/generate/task.rb +34 -51
  74. data/lib/pdk/generate/transport.rb +34 -0
  75. data/lib/pdk/generate.rb +21 -8
  76. data/lib/pdk/logger.rb +24 -6
  77. data/lib/pdk/module/build.rb +125 -37
  78. data/lib/pdk/module/convert.rb +146 -65
  79. data/lib/pdk/module/metadata.rb +72 -71
  80. data/lib/pdk/module/release.rb +255 -0
  81. data/lib/pdk/module/update.rb +48 -37
  82. data/lib/pdk/module/update_manager.rb +75 -39
  83. data/lib/pdk/module.rb +10 -2
  84. data/lib/pdk/monkey_patches.rb +268 -0
  85. data/lib/pdk/report/event.rb +36 -48
  86. data/lib/pdk/report.rb +35 -22
  87. data/lib/pdk/template/fetcher/git.rb +84 -0
  88. data/lib/pdk/template/fetcher/local.rb +29 -0
  89. data/lib/pdk/template/fetcher.rb +100 -0
  90. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +108 -0
  91. data/lib/pdk/template/renderer/v1/renderer.rb +131 -0
  92. data/lib/pdk/template/renderer/v1/template_file.rb +100 -0
  93. data/lib/pdk/template/renderer/v1.rb +25 -0
  94. data/lib/pdk/template/renderer.rb +97 -0
  95. data/lib/pdk/template/template_dir.rb +67 -0
  96. data/lib/pdk/template.rb +52 -0
  97. data/lib/pdk/tests/unit.rb +101 -51
  98. data/lib/pdk/util/bundler.rb +44 -42
  99. data/lib/pdk/util/changelog_generator.rb +138 -0
  100. data/lib/pdk/util/env.rb +48 -0
  101. data/lib/pdk/util/filesystem.rb +139 -2
  102. data/lib/pdk/util/git.rb +108 -8
  103. data/lib/pdk/util/json_finder.rb +86 -0
  104. data/lib/pdk/util/puppet_strings.rb +125 -0
  105. data/lib/pdk/util/puppet_version.rb +71 -87
  106. data/lib/pdk/util/ruby_version.rb +49 -25
  107. data/lib/pdk/util/template_uri.rb +283 -0
  108. data/lib/pdk/util/vendored_file.rb +34 -42
  109. data/lib/pdk/util/version.rb +11 -10
  110. data/lib/pdk/util/windows/api_types.rb +74 -44
  111. data/lib/pdk/util/windows/file.rb +31 -27
  112. data/lib/pdk/util/windows/process.rb +74 -0
  113. data/lib/pdk/util/windows/string.rb +19 -12
  114. data/lib/pdk/util/windows.rb +2 -0
  115. data/lib/pdk/util.rb +111 -124
  116. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
  117. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
  118. data/lib/pdk/validate/external_command_validator.rb +213 -0
  119. data/lib/pdk/validate/internal_ruby_validator.rb +101 -0
  120. data/lib/pdk/validate/invokable_validator.rb +238 -0
  121. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +84 -0
  122. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +76 -0
  123. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
  124. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +131 -0
  125. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
  126. data/lib/pdk/validate/puppet/puppet_plan_syntax_validator.rb +38 -0
  127. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +135 -0
  128. data/lib/pdk/validate/puppet/puppet_validator_group.rb +22 -0
  129. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +79 -0
  130. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
  131. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +83 -0
  132. data/lib/pdk/validate/tasks/tasks_name_validator.rb +45 -0
  133. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
  134. data/lib/pdk/validate/validator.rb +120 -0
  135. data/lib/pdk/validate/validator_group.rb +107 -0
  136. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +86 -0
  137. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
  138. data/lib/pdk/validate.rb +86 -12
  139. data/lib/pdk/version.rb +2 -2
  140. data/lib/pdk.rb +60 -10
  141. metadata +138 -100
  142. data/lib/pdk/cli/module/build.rb +0 -14
  143. data/lib/pdk/cli/module/generate.rb +0 -45
  144. data/lib/pdk/cli/module.rb +0 -14
  145. data/lib/pdk/i18n.rb +0 -4
  146. data/lib/pdk/module/templatedir.rb +0 -321
  147. data/lib/pdk/template_file.rb +0 -95
  148. data/lib/pdk/validate/base_validator.rb +0 -215
  149. data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -86
  150. data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -109
  151. data/lib/pdk/validate/metadata_validator.rb +0 -30
  152. data/lib/pdk/validate/puppet/puppet_lint.rb +0 -67
  153. data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -112
  154. data/lib/pdk/validate/puppet_validator.rb +0 -30
  155. data/lib/pdk/validate/ruby/rubocop.rb +0 -77
  156. data/lib/pdk/validate/ruby_validator.rb +0 -29
  157. data/lib/pdk/validate/tasks/metadata_lint.rb +0 -126
  158. data/lib/pdk/validate/tasks/name.rb +0 -88
  159. data/lib/pdk/validate/tasks_validator.rb +0 -33
  160. data/lib/pdk/validate/yaml/syntax.rb +0 -109
  161. data/lib/pdk/validate/yaml_validator.rb +0 -31
  162. data/locales/config.yaml +0 -21
  163. data/locales/pdk.pot +0 -1291
@@ -1,18 +1,9 @@
1
- require 'fileutils'
2
-
3
1
  require 'pdk'
4
- require 'pdk/logger'
5
- require 'pdk/module/metadata'
6
- require 'pdk/module/templatedir'
7
- require 'pdk/template_file'
8
- require 'pdk/util/filesystem'
9
2
 
10
3
  module PDK
11
4
  module Generate
12
5
  class PuppetObject
13
- attr_reader :module_dir
14
- attr_reader :object_name
15
- attr_reader :options
6
+ attr_reader :context, :object_name, :options
16
7
 
17
8
  # Initialises the PDK::Generate::PuppetObject object.
18
9
  #
@@ -23,170 +14,127 @@ module PDK
23
14
  # OBJECT_TYPE constant and implement the {#template_data},
24
15
  # {#target_object_path} and {#target_spec_path} methods.
25
16
  #
26
- # @param module_dir [String] The path to the module directory that the
17
+ # @param module_dir [String] The path to the root of module that the
27
18
  # will contain the object.
28
19
  # @param object_name [String] The name of the object.
29
20
  # @param options [Hash{Symbol => Object}]
30
- #
31
- # @api public
32
- def initialize(module_dir, object_name, options = {})
33
- @module_dir = module_dir
21
+ def initialize(context, object_name, options)
22
+ raise ArgumentError, format('Expected PDK::Context::AbstractContext but got \'%{klass}\' for context', klass: context.class) unless context.is_a?(PDK::Context::AbstractContext)
23
+
24
+ @context = context
34
25
  @options = options
35
26
  @object_name = object_name
36
-
37
- if [:class, :defined_type].include?(object_type) # rubocop:disable Style/GuardClause
38
- object_name_parts = object_name.split('::')
39
-
40
- @object_name = if object_name_parts.first == module_name
41
- object_name
42
- else
43
- [module_name, object_name].join('::')
44
- end
45
- end
46
27
  end
47
28
 
48
- # @abstract Subclass and implement {#template_data} to provide data to
49
- # the templates during rendering. Implementations of this method should
50
- # return a Hash!{Symbol => Object}.
51
- def template_data
52
- raise NotImplementedError
29
+ # Whether the generator should only return test (spec) files
30
+ # @return [Boolean]
31
+ def spec_only?
32
+ @options[:spec_only]
53
33
  end
54
34
 
55
- # @abstract Subclass and implement {#target_object_path}. Implementations
56
- # of this method should return a String containing the destination path
57
- # of the object being generated.
58
- def target_object_path
35
+ # Subclass and implement {#friendly_name} to provide a nice name to show users in CLI
36
+ # @abstract
37
+ # @return String
38
+ def friendly_name
59
39
  raise NotImplementedError
60
40
  end
61
41
 
62
- # @abstract Subclass and implement {#target_type_path}. Implementations
63
- # of this method should return a String containing the destination path
64
- # of the additional object file being generated.
65
- # @return [String] returns nil if there is no additional object file
66
- def target_type_path
67
- nil
42
+ # Subclass and implement {#template_files} to provide the template files to
43
+ # render. Implementations of this method should return a Hash!{String => String}.
44
+ # @abstract
45
+ # @return Hash{String => String} Hash key is the source template file and the Hash value is
46
+ # the relative destination path
47
+ def template_files
48
+ raise NotImplementedError
68
49
  end
69
50
 
70
- # @abstract Subclass and implement {#target_spec_path}. Implementations
71
- # of this method should return a String containing the destination path
72
- # of the tests for the object being generated.
73
- def target_spec_path
51
+ # Subclass and implement {#template_data} to provide data to the templates during rendering.
52
+ # @abstract
53
+ # @return Hash{Symbol => Object}
54
+ def template_data
74
55
  raise NotImplementedError
75
56
  end
76
57
 
77
- # @abstract Subclass and implement {#target_type_spec_path}. Implementations
78
- # of this method should return a String containing the destination path
79
- # of the tests for the object being generated.
80
- def target_type_spec_path
81
- nil
58
+ # Raises an error if any pre-conditions are not met
59
+ #
60
+ # @return [void]
61
+ # @abstract
62
+ def check_preconditions
63
+ raise ArgumentError, format('Expected a module context but got %{context_name}', context_name: context.display_name) unless context.is_a?(PDK::Context::Module)
82
64
  end
83
65
 
84
- # Retrieves the type of the object being generated, e.g. :class,
85
- # :defined_type, etc. This is specified in the subclass' OBJECT_TYPE
86
- # constant.
87
- #
88
- # @return [Symbol] the type of the object being generated.
66
+ # Check the preconditions of this template group, behaving as a predicate rather than raising an exception.
89
67
  #
68
+ # @return [Boolean] true if the generator is safe to run, otherwise false.
69
+ def can_run?
70
+ check_preconditions
71
+ true
72
+ rescue StandardError
73
+ false
74
+ end
75
+
76
+ # Creates an instance of an update manager
90
77
  # @api private
91
- def object_type
92
- self.class::OBJECT_TYPE
78
+ def update_manager_instance
79
+ require 'pdk/module/update_manager'
80
+ PDK::Module::UpdateManager.new
93
81
  end
94
82
 
95
- # Check preconditions of this template group. By default this only makes sure that the target files do not
96
- # already exist. Override this (and call super) to add your own preconditions.
97
- #
98
- # @raise [PDK::CLI::ExitWithError] if the target files already exist.
83
+ # Stages and then executes the changes for the templates to be rendereed.
84
+ # This is the main entry point for the class.
99
85
  #
86
+ # @see #stage_changes
87
+ # @return [PDK::Module::UpdateManager] The update manager which implemented the changes
100
88
  # @api public
101
- def check_preconditions
102
- [target_object_path, target_type_path, target_spec_path, target_type_spec_path].compact.each do |target_file|
103
- next unless File.exist?(target_file)
104
-
105
- raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % {
106
- file: target_file,
107
- object_type: object_type,
108
- }
109
- end
89
+ def run(update_manager = update_manager_instance)
90
+ stage_changes(update_manager).sync_changes!
91
+ update_manager
110
92
  end
111
93
 
112
94
  # Check that the templates can be rendered. Find an appropriate template
113
- # and create the target files from the template. This is the main entry
95
+ # and stages the target files from the template. This is the main entry
114
96
  # point for the class.
115
97
  #
116
98
  # @raise [PDK::CLI::ExitWithError] if the target files already exist.
117
99
  # @raise [PDK::CLI::FatalError] (see #render_file)
118
- #
100
+ # @return [PDK::Module::UpdateManager] The update manager with the staged changes
119
101
  # @api public
120
- def run
102
+ def stage_changes(update_manager)
121
103
  check_preconditions
122
104
 
123
- with_templates do |template_path, config_hash|
124
- data = template_data.merge(configs: config_hash)
105
+ with_templates do |template_dir|
106
+ template_files.each do |source_file, relative_dest_path|
107
+ new_content = template_dir.render_single_item(source_file, template_data)
108
+ next if new_content.nil?
125
109
 
126
- render_file(target_object_path, template_path[:object], data)
127
- render_file(target_type_path, template_path[:type], data) if template_path[:type]
128
- render_file(target_spec_path, template_path[:spec], data) if template_path[:spec]
129
- render_file(target_type_spec_path, template_path[:type_spec], data) if template_path[:type_spec]
110
+ stage_change(relative_dest_path, new_content, update_manager)
111
+ end
130
112
  end
113
+ non_template_files.each { |relative_dest_path, content| stage_change(relative_dest_path, content, update_manager) }
114
+
115
+ update_manager
131
116
  end
132
117
 
133
- # Render a file using the provided template and write it to disk.
134
- #
135
- # @param dest_path [String] The path that the rendered file should be
136
- # written to. Any necessary directories will be automatically created.
137
- # @param template_path [String] The path on disk to the file containing
138
- # the template.
139
- # @param data [Hash{Object => Object}] The data to be provided to the
140
- # template when rendering.
141
- #
142
- # @raise [PDK::CLI::FatalError] if the parent directories to `dest_path`
143
- # do not exist and could not be created.
144
- # @raise [PDK::CLI::FatalError] if the rendered file could not be written
145
- # to `dest_path`.
146
- #
118
+ # Stages a single file into the Update Manager.
147
119
  # @return [void]
148
- #
149
120
  # @api private
150
- def render_file(dest_path, template_path, data)
151
- write_file(dest_path) do
152
- PDK::TemplateFile.new(template_path, data).render
121
+ def stage_change(relative_dest_path, content, update_manager)
122
+ absolute_file_path = File.join(context.root_path, relative_dest_path)
123
+ if PDK::Util::Filesystem.exist?(absolute_file_path)
124
+ raise PDK::CLI::ExitWithError, format("Unable to generate %{object_type}; '%{file}' already exists.", file: absolute_file_path, object_type: spec_only? ? 'unit test' : friendly_name)
153
125
  end
126
+
127
+ update_manager.add_file(absolute_file_path, content)
154
128
  end
155
129
 
156
- # Write the result of the block to disk.
157
- #
158
- # @param dest_path [String] The path that the rendered file should be
159
- # written to. Any necessary directories will be automatically created.
160
- # @param &block [String] The content to be written
161
- #
162
- # @raise [PDK::CLI::FatalError] if the parent directories to `dest_path`
163
- # do not exist and could not be created.
164
- # @raise [PDK::CLI::FatalError] if the rendered file could not be written
165
- # to `dest_path`.
166
- #
167
- # @return [void]
130
+ # A subclass may wish to stage files into the Update Manager, but the content is not templated. Subclasses
131
+ # can override this method to stage arbitrary files
168
132
  #
169
133
  # @api private
170
- def write_file(dest_path)
171
- PDK.logger.info(_("Creating '%{file}' from template.") % { file: dest_path })
172
-
173
- file_content = yield
174
-
175
- begin
176
- FileUtils.mkdir_p(File.dirname(dest_path))
177
- rescue SystemCallError => e
178
- raise PDK::CLI::FatalError, _("Unable to create directory '%{path}': %{message}") % {
179
- path: File.dirname(dest_path),
180
- message: e.message,
181
- }
182
- end
183
-
184
- PDK::Util::Filesystem.write_file(dest_path, file_content)
185
- rescue SystemCallError => e
186
- raise PDK::CLI::FatalError, _("Unable to write to file '%{path}': %{message}") % {
187
- path: dest_path,
188
- message: e.message,
189
- }
134
+ # @return [Hash{String => String}] A Hash with the relative file path as the key and the new file content as the value.
135
+ # @abstract
136
+ def non_template_files
137
+ {}
190
138
  end
191
139
 
192
140
  # Search the possible template directories in order of preference to find
@@ -204,24 +152,24 @@ module PDK
204
152
  #
205
153
  # @api private
206
154
  def with_templates
155
+ require 'pdk/logger'
156
+ require 'pdk/util/template_uri'
157
+
207
158
  templates.each do |template|
208
- if template[:url].nil?
209
- PDK.logger.debug(_('No %{dir_type} template specified; trying next template directory.') % { dir_type: template[:type] })
159
+ if template[:uri].nil?
160
+ PDK.logger.debug(format('No %{dir_type} template found; trying next template directory.', dir_type: template[:type]))
210
161
  next
211
162
  end
212
163
 
213
- PDK::Module::TemplateDir.new(template[:url]) do |template_dir|
214
- template_paths = template_dir.object_template_for(object_type)
215
-
216
- if template_paths
217
- config_hash = template_dir.object_config
218
- yield template_paths, config_hash
164
+ PDK::Template.with(PDK::Util::TemplateURI.new(template[:uri]), context) do |template_dir|
165
+ if template_files.any? { |source_file, _| template_dir.has_single_item?(source_file) }
166
+ yield template_dir
219
167
  # TODO: refactor to a search-and-execute form instead
220
168
  return # work is done # rubocop:disable Lint/NonLocalExitFromIterator
221
169
  elsif template[:allow_fallback]
222
- PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: object_type, url: template[:url] })
170
+ PDK.logger.debug(format('Unable to find a %{type} template in %{url}; trying next template directory.', type: friendly_name, url: template[:uri]))
223
171
  else
224
- raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: object_type, url: template[:url] }
172
+ raise PDK::CLI::FatalError, format('Unable to find the %{type} template in %{url}.', type: friendly_name, url: template[:uri])
225
173
  end
226
174
  end
227
175
  end
@@ -250,38 +198,31 @@ module PDK
250
198
  #
251
199
  # @api private
252
200
  def templates
253
- @templates ||= [
254
- { type: 'CLI', url: @options[:'template-url'], allow_fallback: false },
255
- { type: 'metadata', url: module_metadata.data['template-url'], allow_fallback: true },
256
- { type: 'default', url: PDK::Util.default_template_url, allow_fallback: false },
257
- ]
201
+ require 'pdk/util/template_uri'
202
+
203
+ @templates ||= PDK::Util::TemplateURI.templates(@options)
258
204
  end
259
205
 
260
206
  # Retrieves the name of the module (without the forge username) from the
261
207
  # module metadata.
262
208
  #
263
- # @raise (see #module_metadata)
264
209
  # @return [String] The name of the module.
265
210
  #
266
211
  # @api private
267
212
  def module_name
268
- @module_name ||= module_metadata.data['name'].rpartition('-').last
213
+ return nil unless context.is_a?(PDK::Context::Module)
214
+
215
+ require 'pdk/util'
216
+ @module_name ||= PDK::Util.module_metadata(context.root_path)['name'].rpartition('-').last
217
+ rescue ArgumentError => e
218
+ raise PDK::CLI::FatalError, e
269
219
  end
270
220
 
271
- # Parses the metadata.json file for the module.
272
- #
273
- # @raise [PDK::CLI::FatalError] if the metadata.json file does not exist,
274
- # can not be read, or contains invalid metadata.
275
- #
276
- # @return [PDK::Module::Metadata] the parsed module metadata.
277
- #
278
- # @api private
279
- def module_metadata
280
- @module_metadata ||= begin
281
- PDK::Module::Metadata.from_file(File.join(module_dir, 'metadata.json'))
282
- rescue ArgumentError => e
283
- raise PDK::CLI::FatalError, _("'%{dir}' does not contain valid Puppet module metadata: %{msg}") % { dir: module_dir, msg: e.message }
284
- end
221
+ private
222
+
223
+ # Transform an object name into a ruby class name
224
+ def class_name_from_object_name(object_name)
225
+ object_name.to_s.split('_').map(&:capitalize).join
285
226
  end
286
227
  end
287
228
  end
@@ -1,46 +1,24 @@
1
- require 'pdk/generate/puppet_object'
1
+ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Generate
5
5
  class Task < PuppetObject
6
- OBJECT_TYPE = :task
7
-
8
- # Prepares the data needed to render the new task template.
9
- #
10
- # @return [Hash{Symbol => Object}] a hash of information that will be
11
- # provided to the task template during rendering. Additionally, this hash
12
- # (with the :name key removed) makes up the task metadata.
13
- def template_data
14
- {
15
- name: object_name,
16
- puppet_task_version: 1,
17
- supports_noop: false,
18
- description: options.fetch(:description, 'A short description of this task'),
19
- parameters: {},
20
- }
6
+ def friendly_name
7
+ 'Task'
21
8
  end
22
9
 
23
- # Calculates the path to the file where the new task will be written.
24
- #
25
- # @return [String] the path to the task file.
26
- def target_object_path
27
- @target_object_path ||= File.join(module_dir, 'tasks', "#{task_name}.sh")
28
- end
10
+ def template_files
11
+ return {} if spec_only?
29
12
 
30
- # Calculates the path to the file where the tests for the new task will
31
- # be written.
32
- #
33
- # @return [nil] as there is currently no test framework for Tasks.
34
- def target_spec_path
35
- nil
13
+ {
14
+ 'task.erb' => File.join('tasks', "#{task_name}.sh")
15
+ }
36
16
  end
37
17
 
38
- def run
39
- check_if_task_already_exists
40
-
41
- super
42
-
43
- write_task_metadata
18
+ def template_data
19
+ {
20
+ name: object_name
21
+ }
44
22
  end
45
23
 
46
24
  # Checks that the task has not already been defined with a different
@@ -48,30 +26,26 @@ module PDK
48
26
  #
49
27
  # @raise [PDK::CLI::ExitWithError] if files with the same name as the
50
28
  # task exist in the <module>/tasks/ directory
51
- #
52
- # @api private
53
- def check_if_task_already_exists
54
- error = _("A task named '%{name}' already exists in this module; defined in %{file}")
55
- allowed_extensions = %w[.md .conf]
29
+ def check_preconditions
30
+ super
31
+
32
+ error = "A task named '%{name}' already exists in this module; defined in %{file}"
33
+ allowed_extensions = ['.md', '.conf']
56
34
 
57
- Dir.glob(File.join(module_dir, 'tasks', "#{task_name}.*")).each do |file|
35
+ PDK::Util::Filesystem.glob(File.join(context.root_path, 'tasks', "#{task_name}.*")).each do |file|
58
36
  next if allowed_extensions.include?(File.extname(file))
59
37
 
60
- raise PDK::CLI::ExitWithError, error % { name: task_name, file: file }
38
+ raise PDK::CLI::ExitWithError, format(error, name: task_name, file: file)
61
39
  end
62
40
  end
63
41
 
64
- # Writes the <module>/tasks/<task_name>.json metadata file for the task.
65
- #
66
- # @api private
67
- def write_task_metadata
68
- write_file(File.join(module_dir, 'tasks', "#{task_name}.json")) do
69
- task_metadata = template_data.dup
70
- task_metadata.delete(:name)
71
- JSON.pretty_generate(task_metadata)
72
- end
42
+ def non_template_files
43
+ task_metadata_file = File.join('tasks', "#{task_name}.json")
44
+ { task_metadata_file => JSON.pretty_generate(task_metadata) }
73
45
  end
74
46
 
47
+ private
48
+
75
49
  # Calculates the file name of the task files ('init' if the task has the
76
50
  # same name as the module, otherwise use the specified task name).
77
51
  #
@@ -79,7 +53,16 @@ module PDK
79
53
  #
80
54
  # @api private
81
55
  def task_name
82
- (object_name == module_name) ? 'init' : object_name
56
+ object_name == module_name ? 'init' : object_name
57
+ end
58
+
59
+ def task_metadata
60
+ {
61
+ puppet_task_version: 1,
62
+ supports_noop: false,
63
+ description: options.fetch(:description, 'A short description of this task'),
64
+ parameters: {}
65
+ }
83
66
  end
84
67
  end
85
68
  end
@@ -0,0 +1,34 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Generate
5
+ class Transport < PuppetObject
6
+ def friendly_name
7
+ 'Resource API Transport'.freeze
8
+ end
9
+
10
+ def template_files
11
+ # NOTE: Due to how the V1 templates work, the names of the source template files may be mismatched to
12
+ # their destination, e.g. transport_type.erb is really a transport schema
13
+ files = {
14
+ 'transport_spec.erb' => "#{File.join('spec', 'unit', 'puppet', 'transport', object_name)}_spec.rb",
15
+ 'transport_type_spec.erb' => "#{File.join('spec', 'unit', 'puppet', 'transport', 'schema', object_name)}_spec.rb"
16
+ }
17
+ return files if spec_only?
18
+
19
+ files.merge(
20
+ 'transport.erb' => "#{File.join('lib', 'puppet', 'transport', object_name)}.rb",
21
+ 'transport_device.erb' => File.join('lib', 'puppet', 'util', 'network_device', object_name, 'device.rb'),
22
+ 'transport_type.erb' => "#{File.join('lib', 'puppet', 'transport', 'schema', object_name)}.rb"
23
+ )
24
+ end
25
+
26
+ def template_data
27
+ {
28
+ name: object_name,
29
+ transport_class: class_name_from_object_name(object_name)
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/pdk/generate.rb CHANGED
@@ -1,11 +1,24 @@
1
- require 'pdk/generate/defined_type'
2
- require 'pdk/generate/module'
3
- require 'pdk/generate/provider'
4
- require 'pdk/generate/puppet_class'
5
- require 'pdk/generate/task'
6
- require 'pdk/module/metadata'
7
- require 'pdk/module/templatedir'
1
+ require 'pdk'
8
2
 
9
3
  module PDK
10
- module Generate; end
4
+ module Generate
5
+ autoload :DefinedType, 'pdk/generate/defined_type'
6
+ autoload :Module, 'pdk/generate/module'
7
+ autoload :Provider, 'pdk/generate/provider'
8
+ autoload :PuppetClass, 'pdk/generate/puppet_class'
9
+ autoload :PuppetObject, 'pdk/generate/puppet_object'
10
+ autoload :Task, 'pdk/generate/task'
11
+ autoload :Transport, 'pdk/generate/transport'
12
+
13
+ def generators
14
+ @generators ||= [
15
+ PDK::Generate::DefinedType,
16
+ PDK::Generate::Provider,
17
+ PDK::Generate::PuppetClass,
18
+ PDK::Generate::Task,
19
+ PDK::Generate::Transport
20
+ ].freeze
21
+ end
22
+ module_function :generators
23
+ end
11
24
  end
data/lib/pdk/logger.rb CHANGED
@@ -1,22 +1,40 @@
1
1
  require 'logger'
2
+ require 'pdk'
2
3
 
3
4
  module PDK
4
- def self.logger
5
- @logger ||= PDK::Logger.new
6
- end
7
-
8
5
  class Logger < ::Logger
6
+ WRAP_COLUMN_LIMIT = 78
7
+
9
8
  def initialize
10
- super(STDERR)
9
+ super($stderr)
10
+ @sent_messages = {}
11
11
 
12
12
  # TODO: Decide on output format.
13
13
  self.formatter = proc do |severity, _datetime, _progname, msg|
14
- "pdk (#{severity}): #{msg}\n"
14
+ prefix = "pdk (#{severity}): "
15
+ if msg.is_a?(Hash)
16
+ if msg.fetch(:wrap, false)
17
+ wrap_pattern = /(.{1,#{WRAP_COLUMN_LIMIT - prefix.length}})(\s+|\Z)/
18
+ "#{prefix}#{msg[:text].gsub(wrap_pattern, "\\1\n#{' ' * prefix.length}")}\n"
19
+ else
20
+ "#{prefix}#{msg[:text]}\n"
21
+ end
22
+ else
23
+ "#{prefix}#{msg}\n"
24
+ end
15
25
  end
16
26
 
17
27
  self.level = ::Logger::INFO
18
28
  end
19
29
 
30
+ def warn_once(*args)
31
+ hash = args.inspect.hash
32
+ return if (@sent_messages[::Logger::WARN] ||= {}).key?(hash)
33
+
34
+ @sent_messages[::Logger::WARN][hash] = true
35
+ warn(*args)
36
+ end
37
+
20
38
  def enable_debug_output
21
39
  self.level = ::Logger::DEBUG
22
40
  end