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,72 +1,68 @@
1
- require 'etc'
2
- require 'pathname'
3
- require 'fileutils'
4
- require 'tty-prompt'
5
-
6
1
  require 'pdk'
7
- require 'pdk/logger'
8
- require 'pdk/module/metadata'
9
- require 'pdk/module/templatedir'
10
- require 'pdk/cli/exec'
11
- require 'pdk/cli/util'
12
- require 'pdk/cli/util/interview'
13
- require 'pdk/cli/util/option_validator'
14
- require 'pdk/util'
15
- require 'pdk/util/version'
16
2
 
17
3
  module PDK
18
4
  module Generate
19
5
  class Module
20
- extend PDK::Util::Filesystem
6
+ def self.validate_options(opts = {})
7
+ require 'pdk/cli/util/option_validator'
21
8
 
22
- def self.validate_options(opts)
23
9
  unless PDK::CLI::Util::OptionValidator.valid_module_name?(opts[:module_name])
24
- error_msg = _(
25
- "'%{module_name}' is not a valid module name.\n" \
26
- 'Module names must begin with a lowercase letter and can only include lowercase letters, digits, and underscores.',
27
- ) % { module_name: opts[:module_name] }
10
+ error_msg = format("'%{module_name}' is not a valid module name.\n" \
11
+ 'Module names must begin with a lowercase letter and can only include lowercase letters, digits, and underscores.', module_name: opts[:module_name])
28
12
  raise PDK::CLI::ExitWithError, error_msg
29
13
  end
30
14
 
31
- target_dir = File.expand_path(opts[:target_dir])
32
- raise PDK::CLI::ExitWithError, _("The destination directory '%{dir}' already exists") % { dir: target_dir } if File.exist?(target_dir)
15
+ target_dir = PDK::Util::Filesystem.expand_path(opts[:target_dir])
16
+ raise PDK::CLI::ExitWithError, format("The destination directory '%{dir}' already exists", dir: target_dir) if PDK::Util::Filesystem.exist?(target_dir)
33
17
  end
34
18
 
35
19
  def self.invoke(opts = {})
20
+ require 'pdk/util'
21
+ require 'pdk/util/template_uri'
22
+ require 'pathname'
23
+
36
24
  validate_options(opts) unless opts[:module_name].nil?
37
25
 
38
26
  metadata = prepare_metadata(opts)
39
27
 
40
- target_dir = File.expand_path(opts[:target_dir] || opts[:module_name])
28
+ target_dir = PDK::Util::Filesystem.expand_path(opts[:target_dir] || opts[:module_name])
41
29
  parent_dir = File.dirname(target_dir)
42
30
 
43
31
  begin
44
32
  test_file = File.join(parent_dir, '.pdk-test-writable')
45
- write_file(test_file, 'This file was created by the Puppet Development Kit to test if this folder was writable, you can safely remove this file.')
46
- FileUtils.rm_f(test_file)
47
- rescue Errno::EACCES
48
- raise PDK::CLI::FatalError, _("You do not have permission to write to '%{parent_dir}'") % {
49
- parent_dir: parent_dir,
50
- }
33
+ PDK::Util::Filesystem.write_file(test_file, 'This file was created by the Puppet Development Kit to test if this folder was writable, you can safely remove this file.')
34
+ PDK::Util::Filesystem.rm_f(test_file)
35
+ rescue Errno::EACCES || Errno::EROFS
36
+ raise PDK::CLI::FatalError, format("You do not have permission to write to '%{parent_dir}'", parent_dir: parent_dir)
51
37
  end
52
38
 
53
39
  temp_target_dir = PDK::Util.make_tmpdir_name('pdk-module-target')
54
40
 
55
41
  prepare_module_directory(temp_target_dir)
56
42
 
57
- template_url = opts.fetch(:'template-url', PDK::Util.default_template_url)
43
+ template_uri = PDK::Util::TemplateURI.new(opts)
44
+
45
+ if template_uri.default? && template_uri.default_ref?
46
+ PDK.logger.info 'Using the default template-url and template-ref.'
47
+ else
48
+ PDK.logger.info format("Using the %{method} template-url and template-ref '%{template_uri}'.", method: opts.key?(:'template-url') ? 'specified' : 'saved',
49
+ template_uri: template_uri.metadata_format)
50
+ end
58
51
 
59
52
  begin
60
- PDK::Module::TemplateDir.new(template_url, metadata.data, true) do |templates|
61
- templates.render do |file_path, file_content|
62
- file = Pathname.new(temp_target_dir) + file_path
53
+ context = PDK::Context::None.new(temp_target_dir)
54
+ PDK::Template.with(template_uri, context) do |template_dir|
55
+ template_dir.render_new_module(metadata.data['name'], metadata.data) do |relative_file_path, file_content, file_status|
56
+ next if [:delete, :unmanage].include?(file_status)
57
+
58
+ file = Pathname.new(temp_target_dir) + relative_file_path
63
59
  file.dirname.mkpath
64
- write_file(file, file_content)
60
+ PDK::Util::Filesystem.write_file(file, file_content)
65
61
  end
66
62
 
67
63
  # Add information about the template used to generate the module to the
68
64
  # metadata (for a future update command).
69
- metadata.update!(templates.metadata)
65
+ metadata.update!(template_dir.metadata)
70
66
 
71
67
  metadata.write!(File.join(temp_target_dir, 'metadata.json'))
72
68
  end
@@ -74,58 +70,71 @@ module PDK
74
70
  raise PDK::CLI::ExitWithError, e
75
71
  end
76
72
 
77
- if template_url == PDK::Util.puppetlabs_template_url
78
- # If the user specifies our template via the command line, remove the
79
- # saved template-url answer.
80
- PDK.answers.update!('template-url' => nil) if opts.key?(:'template-url')
73
+ # Only update the answers files after metadata has been written.
74
+ require 'pdk/answer_file'
75
+ if template_uri.default? && template_uri.default_ref?
76
+ # If the user specifies our default template url via the command
77
+ # line, remove the saved template-url answer so that the template_uri
78
+ # resolution can find new default URLs in the future.
79
+ PDK.config.set(['user', 'module_defaults', 'template-url'], nil) if opts.key?(:'template-url')
81
80
  else
82
- # Save the template-url answer if the module was generated using
83
- # a template other than ours.
84
- PDK.answers.update!('template-url' => template_url)
81
+ # Save the template-url answers if the module was generated using a
82
+ # template/reference other than ours.
83
+ PDK.config.set(['user', 'module_defaults', 'template-url'], template_uri.metadata_format)
85
84
  end
86
85
 
87
86
  begin
88
- if FileUtils.mv(temp_target_dir, target_dir)
89
- Dir.chdir(target_dir) { PDK::Util::Bundler.ensure_bundle! } unless opts[:'skip-bundle-install']
87
+ if PDK::Util::Filesystem.mv(temp_target_dir, target_dir)
88
+ unless opts[:'skip-bundle-install']
89
+ Dir.chdir(target_dir) do
90
+ require 'pdk/util/bundler'
91
+ PDK::Util::Bundler.ensure_bundle!
92
+ end
93
+ end
90
94
 
91
- PDK.logger.info(_('Module \'%{name}\' generated at path \'%{path}\', from template \'%{template_url}\'.') % { name: opts[:module_name], path: target_dir, template_url: template_url })
92
- PDK.logger.info(_('In your module directory, add classes with the \'pdk new class\' command.'))
95
+ PDK.logger.info format("Module '%{name}' generated at path '%{path}'.", name: opts[:module_name], path: target_dir)
96
+ PDK.logger.info "In your module directory, add classes with the 'pdk new class' command."
93
97
  end
94
98
  rescue Errno::EACCES => e
95
- raise PDK::CLI::FatalError, _("Failed to move '%{source}' to '%{target}': %{message}") % {
96
- source: temp_target_dir,
97
- target: target_dir,
98
- message: e.message,
99
- }
99
+ raise PDK::CLI::FatalError, format("Failed to move '%{source}' to '%{target}': %{message}", source: temp_target_dir, target: target_dir, message: e.message)
100
100
  end
101
101
  end
102
102
 
103
103
  def self.username_from_login
104
+ require 'etc'
105
+
104
106
  login = Etc.getlogin || ''
105
- login_clean = login.downcase.gsub(%r{[^0-9a-z]}i, '')
107
+ login_clean = login.downcase.gsub(/[^0-9a-z]/i, '')
106
108
  login_clean = 'username' if login_clean.empty?
107
109
 
108
110
  if login_clean != login
109
- PDK.logger.debug _('Your username is not a valid Forge username. Proceeding with the username %{username}. You can fix this later in metadata.json.') % {
110
- username: login_clean,
111
- }
111
+ PDK.logger.debug format('Your username is not a valid Forge username. Proceeding with the username %{username}. You can fix this later in metadata.json.', username: login_clean)
112
112
  end
113
113
 
114
114
  login_clean
115
115
  end
116
116
 
117
117
  def self.prepare_metadata(opts = {})
118
- opts[:username] = (opts[:username] || PDK.answers['forge_username'] || username_from_login).downcase
118
+ require 'pdk/answer_file'
119
+ require 'pdk/module/metadata'
120
+
121
+ opts[:username] = (opts[:username] || PDK.config.get_within_scopes('module_defaults.forge_username') || username_from_login).downcase
119
122
 
120
123
  defaults = PDK::Module::Metadata::DEFAULTS.dup
121
124
 
122
125
  defaults['name'] = "#{opts[:username]}-#{opts[:module_name]}" unless opts[:module_name].nil?
123
- defaults['author'] = PDK.answers['author'] unless PDK.answers['author'].nil?
124
- defaults['license'] = PDK.answers['license'] unless PDK.answers['license'].nil?
125
- defaults['license'] = opts[:license] if opts.key? :license
126
+ PDK.config.with_scoped_value('module_defaults.author') { |val| defaults['author'] = val }
127
+ PDK.config.with_scoped_value('module_defaults.license') { |val| defaults['license'] = val }
128
+ defaults['license'] = opts[:license] if opts.key?(:license)
129
+ PDK.config.with_scoped_value('module_defaults.operatingsystem_support') { |val| defaults['operatingsystem_support'] = val }
126
130
 
127
131
  metadata = PDK::Module::Metadata.new(defaults)
128
- module_interview(metadata, opts) unless opts[:'skip-interview']
132
+
133
+ if opts[:'skip-interview']
134
+ metadata.data['operatingsystem_support'] = metadata.data['operatingsystem_support'].map { |val| PDK::Module::Metadata::OPERATING_SYSTEMS[val] }.flatten
135
+ else
136
+ module_interview(metadata, opts)
137
+ end
129
138
 
130
139
  metadata
131
140
  end
@@ -136,103 +145,102 @@ module PDK
136
145
  File.join(target_dir, 'files'),
137
146
  File.join(target_dir, 'manifests'),
138
147
  File.join(target_dir, 'templates'),
139
- File.join(target_dir, 'tasks'),
148
+ File.join(target_dir, 'tasks')
140
149
  ].each do |dir|
141
- begin
142
- FileUtils.mkdir_p(dir)
143
- rescue SystemCallError => e
144
- raise PDK::CLI::FatalError, _("Unable to create directory '%{dir}': %{message}") % {
145
- dir: dir,
146
- message: e.message,
147
- }
148
- end
150
+ PDK::Util::Filesystem.mkdir_p(dir)
151
+ rescue SystemCallError => e
152
+ raise PDK::CLI::FatalError, format("Unable to create directory '%{dir}': %{message}", dir: dir, message: e.message)
149
153
  end
150
154
  end
151
155
 
152
156
  def self.module_interview(metadata, opts = {})
157
+ require 'pdk/module/metadata'
158
+ require 'pdk/cli/util/interview'
159
+
153
160
  questions = [
154
161
  {
155
- name: 'module_name',
156
- question: _('If you have a name for your module, add it here.'),
157
- help: _('This is the name that will be associated with your module, it should be relevant to the modules content.'),
158
- required: true,
159
- validate_pattern: %r{\A[a-z][a-z0-9_]*\Z}i,
160
- validate_message: _('Module names must begin with a lowercase letter and can only include lowercase letters, numbers, and underscores.'),
162
+ name: 'module_name',
163
+ question: 'If you have a name for your module, add it here.',
164
+ help: 'This is the name that will be associated with your module, it should be relevant to the modules content.',
165
+ required: true,
166
+ validate_pattern: /\A[a-z][a-z0-9_]*\Z/i,
167
+ validate_message: 'Module names must begin with a lowercase letter and can only include lowercase letters, numbers, and underscores.'
161
168
  },
162
169
  {
163
- name: 'forge_username',
164
- question: _('If you have a Puppet Forge username, add it here.'),
165
- help: _('We can use this to upload your module to the Forge when it\'s complete.'),
166
- required: true,
167
- validate_pattern: %r{\A[a-z0-9]+\Z}i,
168
- validate_message: _('Forge usernames can only contain lowercase letters and numbers'),
169
- default: opts[:username],
170
+ name: 'forge_username',
171
+ question: 'If you have a Puppet Forge username, add it here.',
172
+ help: 'We can use this to upload your module to the Forge when it\'s complete.',
173
+ required: true,
174
+ validate_pattern: /\A[a-z0-9]+\Z/i,
175
+ validate_message: 'Forge usernames can only contain lowercase letters and numbers',
176
+ default: opts[:username]
170
177
  },
171
178
  {
172
- name: 'version',
173
- question: _('What version is this module?'),
174
- help: _('Puppet uses Semantic Versioning (semver.org) to version modules.'),
175
- required: true,
176
- validate_pattern: %r{\A[0-9]+\.[0-9]+\.[0-9]+},
177
- validate_message: _('Semantic Version numbers must be in the form MAJOR.MINOR.PATCH'),
178
- default: metadata.data['version'],
179
- forge_only: true,
179
+ name: 'version',
180
+ question: 'What version is this module?',
181
+ help: 'Puppet uses Semantic Versioning (semver.org) to version modules.',
182
+ required: true,
183
+ validate_pattern: /\A[0-9]+\.[0-9]+\.[0-9]+/i,
184
+ validate_message: 'Semantic Version numbers must be in the form MAJOR.MINOR.PATCH',
185
+ default: metadata.data['version'],
186
+ forge_only: true
180
187
  },
181
188
  {
182
- name: 'author',
183
- question: _('Who wrote this module?'),
184
- help: _('This is used to credit the module\'s author.'),
189
+ name: 'author',
190
+ question: 'Who wrote this module?',
191
+ help: 'This is used to credit the module\'s author.',
185
192
  required: true,
186
- default: metadata.data['author'],
193
+ default: metadata.data['author']
187
194
  },
188
195
  {
189
- name: 'license',
190
- question: _('What license does this module code fall under?'),
191
- help: _('This should be an identifier from https://spdx.org/licenses/. Common values are "Apache-2.0", "MIT", or "proprietary".'),
196
+ name: 'license',
197
+ question: 'What license does this module code fall under?',
198
+ help: 'This should be an identifier from https://spdx.org/licenses/. Common values are "Apache-2.0", "MIT", or "proprietary".',
192
199
  required: true,
193
- default: metadata.data['license'],
200
+ default: metadata.data['license']
194
201
  },
195
202
  {
196
- name: 'operatingsystem_support',
197
- question: _('What operating systems does this module support?'),
198
- help: _('Use the up and down keys to move between the choices, space to select and enter to continue.'),
203
+ name: 'operatingsystem_support',
204
+ question: 'What operating systems does this module support?',
205
+ help: 'Use the up and down keys to move between the choices, space to select and enter to continue.',
199
206
  required: true,
200
- choices: PDK::Module::Metadata::OPERATING_SYSTEMS,
201
- default: PDK::Module::Metadata::DEFAULT_OPERATING_SYSTEMS.map do |os_name|
207
+ type: :multi_select,
208
+ choices: PDK::Module::Metadata::OPERATING_SYSTEMS,
209
+ default: metadata.data['operatingsystem_support'] do |os_name|
202
210
  # tty-prompt uses a 1-index
203
211
  PDK::Module::Metadata::OPERATING_SYSTEMS.keys.index(os_name) + 1
204
- end,
212
+ end
205
213
  },
206
214
  {
207
- name: 'summary',
208
- question: _('Summarize the purpose of this module in a single sentence.'),
209
- help: _('This helps other Puppet users understand what the module does.'),
210
- required: true,
211
- default: metadata.data['summary'],
212
- forge_only: true,
215
+ name: 'summary',
216
+ question: 'Summarize the purpose of this module in a single sentence.',
217
+ help: 'This helps other Puppet users understand what the module does.',
218
+ required: true,
219
+ default: metadata.data['summary'],
220
+ forge_only: true
213
221
  },
214
222
  {
215
- name: 'source',
216
- question: _('If there is a source code repository for this module, enter the URL here.'),
217
- help: _('Skip this if no repository exists yet. You can update this later in the metadata.json.'),
218
- required: true,
219
- default: metadata.data['source'],
220
- forge_only: true,
223
+ name: 'source',
224
+ question: 'If there is a source code repository for this module, enter the URL here.',
225
+ help: 'Skip this if no repository exists yet. You can update this later in the metadata.json.',
226
+ required: true,
227
+ default: metadata.data['source'],
228
+ forge_only: true
221
229
  },
222
230
  {
223
- name: 'project_page',
224
- question: _('If there is a URL where others can learn more about this module, enter it here.'),
225
- help: _('Optional. You can update this later in the metadata.json.'),
226
- default: metadata.data['project_page'],
227
- forge_only: true,
231
+ name: 'project_page',
232
+ question: 'If there is a URL where others can learn more about this module, enter it here.',
233
+ help: 'Optional. You can update this later in the metadata.json.',
234
+ default: metadata.data['project_page'],
235
+ forge_only: true
228
236
  },
229
237
  {
230
- name: 'issues_url',
231
- question: _('If there is a public issue tracker for this module, enter its URL here.'),
232
- help: _('Optional. You can update this later in the metadata.json.'),
233
- default: metadata.data['issues_url'],
234
- forge_only: true,
235
- },
238
+ name: 'issues_url',
239
+ question: 'If there is a public issue tracker for this module, enter its URL here.',
240
+ help: 'Optional. You can update this later in the metadata.json.',
241
+ default: metadata.data['issues_url'],
242
+ forge_only: true
243
+ }
236
244
  ]
237
245
 
238
246
  prompt = TTY::Prompt.new(help_color: :cyan)
@@ -241,8 +249,8 @@ module PDK
241
249
 
242
250
  if opts[:only_ask]
243
251
  questions.reject! do |question|
244
- if %w[module_name forge_username].include?(question[:name])
245
- metadata.data['name'] && metadata.data['name'] =~ %r{\A[a-z0-9]+-[a-z][a-z0-9_]*\Z}i
252
+ if ['module_name', 'forge_username'].include?(question[:name])
253
+ metadata.data['name'] && metadata.data['name'] =~ /\A[a-z0-9]+-[a-z][a-z0-9_]*\Z/i
246
254
  else
247
255
  !opts[:only_ask].include?(question[:name])
248
256
  end
@@ -250,27 +258,27 @@ module PDK
250
258
  else
251
259
  questions.reject! { |q| q[:name] == 'module_name' } if opts.key?(:module_name)
252
260
  questions.reject! { |q| q[:name] == 'license' } if opts.key?(:license)
253
- questions.reject! { |q| q[:forge_only] } unless opts.key?(:'full-interview')
261
+ questions.reject! { |q| q[:forge_only] } unless opts[:'full-interview']
254
262
  end
255
263
 
256
264
  interview.add_questions(questions)
257
265
 
258
- action = File.file?('metadata.json') ? _('update') : _('create')
259
- puts _(
260
- "\nWe need to %{action} the metadata.json file for this module, so we\'re going to ask you %{count} " \
261
- "questions.\n" \
262
- 'If the question is not applicable to this module, accept the default option ' \
263
- 'shown after each question. You can modify any answers at any time by manually updating ' \
264
- "the metadata.json file.\n\n",
265
- ) % {
266
- count: interview.num_questions,
267
- action: action,
268
- }
266
+ if PDK::Util::Filesystem.file?('metadata.json')
267
+ puts format("\nWe need to update the metadata.json file for this module, so we're going to ask you %{count} " \
268
+ "questions.\n", count: interview.num_questions)
269
+ else
270
+ puts format("\nWe need to create the metadata.json file for this module, so we're going to ask you %{count} " \
271
+ "questions.\n", count: interview.num_questions)
272
+ end
273
+
274
+ puts 'If the question is not applicable to this module, accept the default option ' \
275
+ 'shown after each question. You can modify any answers at any time by manually updating ' \
276
+ "the metadata.json file.\n\n"
269
277
 
270
278
  answers = interview.run
271
279
 
272
280
  if answers.nil?
273
- PDK.logger.info _('No answers given, interview cancelled.')
281
+ PDK.logger.info 'No answers given, interview cancelled.'
274
282
  exit 0
275
283
  end
276
284
 
@@ -293,25 +301,24 @@ module PDK
293
301
  metadata.update!(answers)
294
302
 
295
303
  if opts[:prompt].nil? || opts[:prompt]
304
+ require 'pdk/cli/util'
305
+
296
306
  continue = PDK::CLI::Util.prompt_for_yes(
297
- _('Metadata will be generated based on this information, continue?'),
298
- prompt: prompt,
299
- cancel_message: _('Interview cancelled; exiting.'),
307
+ 'Metadata will be generated based on this information, continue?',
308
+ prompt: prompt,
309
+ cancel_message: 'Interview cancelled; exiting.'
300
310
  )
301
311
 
302
312
  unless continue
303
- PDK.logger.info _('Process cancelled; exiting.')
313
+ PDK.logger.info 'Process cancelled; exiting.'
304
314
  exit 0
305
315
  end
306
316
  end
307
317
 
308
- PDK.answers.update!(
309
- {
310
- 'forge_username' => opts[:username],
311
- 'author' => answers['author'],
312
- 'license' => answers['license'],
313
- }.delete_if { |_key, value| value.nil? },
314
- )
318
+ require 'pdk/answer_file'
319
+ PDK.config.set(['user', 'module_defaults', 'forge_username'], opts[:username]) unless opts[:username].nil?
320
+ PDK.config.set(['user', 'module_defaults', 'author'], answers['author']) unless answers['author'].nil?
321
+ PDK.config.set(['user', 'module_defaults', 'license'], answers['license']) unless answers['license'].nil?
315
322
  end
316
323
  end
317
324
  end
@@ -1,81 +1,28 @@
1
- require 'pdk/generate/puppet_object'
1
+ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Generate
5
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://github.com/puppetlabs/puppet-resource_api#getting-started.') % { 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
6
+ def friendly_name
7
+ 'Resource API Provider'.freeze
53
8
  end
54
9
 
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'
58
- end
59
-
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'
69
- end
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?
70
16
 
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'
17
+ files.merge(
18
+ 'provider.erb' => "#{File.join('lib', 'puppet', 'provider', object_name, object_name)}.rb",
19
+ 'provider_type.erb' => "#{File.join('lib', 'puppet', 'type', object_name)}.rb"
20
+ )
74
21
  end
75
22
 
76
- # transform a object name into a ruby class name
77
- def self.class_name_from_object_name(object_name)
78
- object_name.to_s.split('_').map(&:capitalize).join
23
+ def template_data
24
+ { name: object_name,
25
+ provider_class: class_name_from_object_name(object_name) }
79
26
  end
80
27
  end
81
28
  end
@@ -1,47 +1,42 @@
1
- require 'pdk/generate/puppet_object'
1
+ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Generate
5
5
  class PuppetClass < PuppetObject
6
- OBJECT_TYPE = :class
6
+ PUPPET_STRINGS_TYPE = 'puppet_classes'.freeze
7
7
 
8
- # Prepares the data needed to render the new Puppet class template.
9
- #
10
- # @return [Hash{Symbol => Object}] a hash of information that will be
11
- # provided to the class and class spec templates during rendering.
12
- def template_data
13
- data = { name: object_name }
8
+ def initialize(*_args)
9
+ super
10
+ object_name_parts = @object_name.split('::')
14
11
 
15
- data
12
+ @object_name = if object_name_parts.first == module_name
13
+ object_name
14
+ else
15
+ [module_name, object_name].join('::')
16
+ end
16
17
  end
17
18
 
18
- # Calculates the path to the .pp file that the new class will be written
19
- # to.
20
- #
21
- # @return [String] the path where the new class will be written.
22
- def target_object_path
23
- @target_pp_path ||= begin
24
- class_name_parts = object_name.split('::')[1..-1]
25
- class_name_parts << 'init' if class_name_parts.empty?
26
-
27
- "#{File.join(module_dir, 'manifests', *class_name_parts)}.pp"
28
- end
19
+ def friendly_name
20
+ 'Puppet Class'.freeze
29
21
  end
30
22
 
31
- # Calculates the path to the file where the tests for the new class will
32
- # be written.
33
- #
34
- # @return [String] the path where the tests for the new class will be
35
- # written.
36
- def target_spec_path
37
- @target_spec_path ||= begin
38
- 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..]
32
+ class_name_parts << 'init' if class_name_parts.empty?
33
+ files['class.erb'] = "#{File.join('manifests', *class_name_parts)}.pp"
39
34
 
40
- # drop the module name if the object name contains multiple parts
41
- class_name_parts.delete_at(0) if class_name_parts.length > 1
35
+ files
36
+ end
42
37
 
43
- "#{File.join(module_dir, 'spec', 'classes', *class_name_parts)}_spec.rb"
44
- end
38
+ def template_data
39
+ { name: object_name }
45
40
  end
46
41
  end
47
42
  end