pdk 2.3.0 → 2.4.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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1329 -1321
  3. data/LICENSE +201 -201
  4. data/README.md +163 -163
  5. data/exe/pdk +10 -10
  6. data/lib/pdk/analytics/client/google_analytics.rb +143 -143
  7. data/lib/pdk/analytics/client/noop.rb +25 -25
  8. data/lib/pdk/analytics/util.rb +19 -19
  9. data/lib/pdk/analytics.rb +30 -30
  10. data/lib/pdk/answer_file.rb +12 -12
  11. data/lib/pdk/bolt.rb +19 -19
  12. data/lib/pdk/cli/build.rb +82 -82
  13. data/lib/pdk/cli/bundle.rb +48 -48
  14. data/lib/pdk/cli/config/get.rb +26 -26
  15. data/lib/pdk/cli/config.rb +22 -22
  16. data/lib/pdk/cli/console.rb +148 -148
  17. data/lib/pdk/cli/convert.rb +52 -52
  18. data/lib/pdk/cli/env.rb +52 -52
  19. data/lib/pdk/cli/errors.rb +25 -25
  20. data/lib/pdk/cli/exec/command.rb +293 -293
  21. data/lib/pdk/cli/exec/interactive_command.rb +114 -114
  22. data/lib/pdk/cli/exec.rb +84 -84
  23. data/lib/pdk/cli/exec_group.rb +104 -104
  24. data/lib/pdk/cli/get/config.rb +24 -24
  25. data/lib/pdk/cli/get.rb +20 -20
  26. data/lib/pdk/cli/module/build.rb +12 -12
  27. data/lib/pdk/cli/module/generate.rb +47 -47
  28. data/lib/pdk/cli/module.rb +14 -14
  29. data/lib/pdk/cli/new/class.rb +32 -32
  30. data/lib/pdk/cli/new/defined_type.rb +32 -32
  31. data/lib/pdk/cli/new/fact.rb +29 -29
  32. data/lib/pdk/cli/new/function.rb +29 -29
  33. data/lib/pdk/cli/new/module.rb +53 -53
  34. data/lib/pdk/cli/new/provider.rb +29 -29
  35. data/lib/pdk/cli/new/task.rb +34 -34
  36. data/lib/pdk/cli/new/test.rb +52 -52
  37. data/lib/pdk/cli/new/transport.rb +27 -27
  38. data/lib/pdk/cli/new.rb +21 -21
  39. data/lib/pdk/cli/release/prep.rb +39 -39
  40. data/lib/pdk/cli/release/publish.rb +50 -50
  41. data/lib/pdk/cli/release.rb +194 -194
  42. data/lib/pdk/cli/remove/config.rb +80 -80
  43. data/lib/pdk/cli/remove.rb +20 -20
  44. data/lib/pdk/cli/set/config.rb +119 -119
  45. data/lib/pdk/cli/set.rb +20 -20
  46. data/lib/pdk/cli/test/unit.rb +90 -90
  47. data/lib/pdk/cli/test.rb +11 -11
  48. data/lib/pdk/cli/update.rb +64 -64
  49. data/lib/pdk/cli/util/command_redirector.rb +27 -27
  50. data/lib/pdk/cli/util/interview.rb +72 -72
  51. data/lib/pdk/cli/util/option_normalizer.rb +55 -55
  52. data/lib/pdk/cli/util/option_validator.rb +68 -68
  53. data/lib/pdk/cli/util/spinner.rb +13 -13
  54. data/lib/pdk/cli/util/update_manager_printer.rb +82 -82
  55. data/lib/pdk/cli/util.rb +305 -305
  56. data/lib/pdk/cli/validate.rb +116 -116
  57. data/lib/pdk/cli.rb +175 -175
  58. data/lib/pdk/config/analytics_schema.json +26 -26
  59. data/lib/pdk/config/errors.rb +5 -5
  60. data/lib/pdk/config/ini_file.rb +183 -183
  61. data/lib/pdk/config/ini_file_setting.rb +39 -39
  62. data/lib/pdk/config/json.rb +34 -34
  63. data/lib/pdk/config/json_schema_namespace.rb +142 -142
  64. data/lib/pdk/config/json_schema_setting.rb +53 -53
  65. data/lib/pdk/config/json_with_schema.rb +49 -49
  66. data/lib/pdk/config/namespace.rb +354 -354
  67. data/lib/pdk/config/setting.rb +135 -135
  68. data/lib/pdk/config/validator.rb +31 -31
  69. data/lib/pdk/config/yaml.rb +46 -46
  70. data/lib/pdk/config/yaml_with_schema.rb +59 -59
  71. data/lib/pdk/config.rb +390 -390
  72. data/lib/pdk/context/control_repo.rb +60 -60
  73. data/lib/pdk/context/module.rb +28 -28
  74. data/lib/pdk/context/none.rb +22 -22
  75. data/lib/pdk/context.rb +99 -99
  76. data/lib/pdk/control_repo.rb +90 -90
  77. data/lib/pdk/generate/defined_type.rb +43 -43
  78. data/lib/pdk/generate/fact.rb +25 -25
  79. data/lib/pdk/generate/function.rb +48 -48
  80. data/lib/pdk/generate/module.rb +352 -352
  81. data/lib/pdk/generate/provider.rb +28 -28
  82. data/lib/pdk/generate/puppet_class.rb +43 -43
  83. data/lib/pdk/generate/puppet_object.rb +232 -232
  84. data/lib/pdk/generate/task.rb +68 -68
  85. data/lib/pdk/generate/transport.rb +33 -33
  86. data/lib/pdk/generate.rb +24 -24
  87. data/lib/pdk/i18n.rb +4 -4
  88. data/lib/pdk/logger.rb +45 -45
  89. data/lib/pdk/module/build.rb +322 -322
  90. data/lib/pdk/module/convert.rb +296 -296
  91. data/lib/pdk/module/metadata.rb +202 -202
  92. data/lib/pdk/module/release.rb +260 -260
  93. data/lib/pdk/module/update.rb +131 -131
  94. data/lib/pdk/module/update_manager.rb +227 -227
  95. data/lib/pdk/module.rb +30 -30
  96. data/lib/pdk/report/event.rb +370 -370
  97. data/lib/pdk/report.rb +121 -121
  98. data/lib/pdk/template/fetcher/git.rb +85 -85
  99. data/lib/pdk/template/fetcher/local.rb +28 -28
  100. data/lib/pdk/template/fetcher.rb +98 -98
  101. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +116 -116
  102. data/lib/pdk/template/renderer/v1/renderer.rb +132 -132
  103. data/lib/pdk/template/renderer/v1/template_file.rb +102 -102
  104. data/lib/pdk/template/renderer/v1.rb +25 -25
  105. data/lib/pdk/template/renderer.rb +96 -96
  106. data/lib/pdk/template/template_dir.rb +67 -67
  107. data/lib/pdk/template.rb +59 -59
  108. data/lib/pdk/tests/unit.rb +252 -252
  109. data/lib/pdk/util/bundler.rb +259 -259
  110. data/lib/pdk/util/changelog_generator.rb +137 -137
  111. data/lib/pdk/util/env.rb +47 -47
  112. data/lib/pdk/util/filesystem.rb +138 -138
  113. data/lib/pdk/util/git.rb +179 -179
  114. data/lib/pdk/util/json_finder.rb +85 -85
  115. data/lib/pdk/util/puppet_strings.rb +125 -125
  116. data/lib/pdk/util/puppet_version.rb +266 -266
  117. data/lib/pdk/util/ruby_version.rb +179 -179
  118. data/lib/pdk/util/template_uri.rb +295 -295
  119. data/lib/pdk/util/vendored_file.rb +93 -93
  120. data/lib/pdk/util/version.rb +43 -43
  121. data/lib/pdk/util/windows/api_types.rb +82 -82
  122. data/lib/pdk/util/windows/file.rb +36 -36
  123. data/lib/pdk/util/windows/process.rb +79 -79
  124. data/lib/pdk/util/windows/string.rb +16 -16
  125. data/lib/pdk/util/windows.rb +15 -15
  126. data/lib/pdk/util.rb +278 -277
  127. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -23
  128. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -98
  129. data/lib/pdk/validate/external_command_validator.rb +208 -208
  130. data/lib/pdk/validate/internal_ruby_validator.rb +100 -100
  131. data/lib/pdk/validate/invokable_validator.rb +228 -228
  132. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +86 -86
  133. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +78 -78
  134. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -20
  135. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +133 -133
  136. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -66
  137. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +137 -137
  138. data/lib/pdk/validate/puppet/puppet_validator_group.rb +21 -21
  139. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +80 -80
  140. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -19
  141. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +88 -88
  142. data/lib/pdk/validate/tasks/tasks_name_validator.rb +50 -50
  143. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -20
  144. data/lib/pdk/validate/validator.rb +118 -118
  145. data/lib/pdk/validate/validator_group.rb +104 -104
  146. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +95 -95
  147. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -19
  148. data/lib/pdk/validate.rb +94 -94
  149. data/lib/pdk/version.rb +4 -4
  150. data/lib/pdk.rb +76 -76
  151. data/locales/config.yaml +21 -21
  152. data/locales/pdk.pot +2094 -2094
  153. metadata +5 -6
@@ -1,266 +1,266 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Util
5
- class PuppetVersion
6
- class << self
7
- extend Forwardable
8
-
9
- def_delegators :instance, :puppet_dev_env, :puppet_dev_path, :fetch_puppet_dev, :find_gem_for, :from_pe_version, :from_module_metadata, :latest_available
10
-
11
- attr_writer :instance
12
-
13
- def instance
14
- @instance ||= new
15
- end
16
- end
17
-
18
- PE_VERSIONS_URL = 'https://forgeapi.puppet.com/private/versions/pe'.freeze
19
- DEFAULT_PUPPET_DEV_URL = 'https://github.com/puppetlabs/puppet'.freeze
20
- DEFAULT_PUPPET_DEV_BRANCH = 'main'.freeze
21
-
22
- def puppet_dev_env
23
- require 'pdk/util/ruby_version'
24
-
25
- {
26
- gem_version: 'file://%{path}' % { path: puppet_dev_path },
27
- ruby_version: PDK::Util::RubyVersion.latest_ruby_version,
28
- }
29
- end
30
-
31
- def puppet_dev_path
32
- require 'pdk/util'
33
-
34
- File.join(PDK::Util.cachedir, 'src', 'puppet')
35
- end
36
-
37
- def latest_available
38
- latest = find_gem(Gem::Requirement.create('>= 0'))
39
-
40
- if latest.nil?
41
- raise ArgumentError, _('Unable to find a Puppet gem in current Ruby environment or from Rubygems.org.')
42
- end
43
-
44
- latest
45
- end
46
-
47
- def puppet_dev_fetched?
48
- !@puppet_dev_fetched.nil?
49
- end
50
-
51
- def fetch_puppet_dev(options = {})
52
- return if options[:run] == :once && puppet_dev_fetched?
53
-
54
- require 'pdk/util/git'
55
-
56
- # Check if the source is cloned and is a readable git repo
57
- unless PDK::Util::Git.remote_repo? puppet_dev_path
58
- # Check if the path has something in it already. Delete it and prepare for clone if so.
59
- if PDK::Util::Filesystem.exist? puppet_dev_path
60
- PDK::Util::Filesystem.delete(puppet_dev_path) if PDK::Util::Filesystem.file? puppet_dev_path
61
- PDK::Util::Filesystem.rm_rf(puppet_dev_path) if PDK::Util::Filesystem.directory? puppet_dev_path
62
- end
63
-
64
- PDK::Util::Filesystem.mkdir_p puppet_dev_path
65
- clone_result = PDK::Util::Git.git('clone', DEFAULT_PUPPET_DEV_URL, puppet_dev_path)
66
- return if clone_result[:exit_code].zero?
67
-
68
- PDK.logger.error clone_result[:stdout]
69
- PDK.logger.error clone_result[:stderr]
70
- raise PDK::CLI::FatalError, _("Unable to clone git repository from '%{repo}'.") % { repo: DEFAULT_PUPPET_DEV_URL }
71
- end
72
-
73
- # Fetch Updates from remote repository
74
- fetch_result = PDK::Util::Git.git('-C', puppet_dev_path, 'fetch', 'origin')
75
-
76
- unless fetch_result[:exit_code].zero?
77
- PDK.logger.error fetch_result[:stdout]
78
- PDK.logger.error fetch_result[:stderr]
79
- raise PDK::CLI::FatalError, _("Unable to fetch from git remote at '%{repo}'.") % { repo: DEFAULT_PUPPET_DEV_URL }
80
- end
81
-
82
- # Reset local repo to latest
83
- reset_result = PDK::Util::Git.git('-C', puppet_dev_path, 'reset', '--hard', "origin/#{DEFAULT_PUPPET_DEV_BRANCH}")
84
-
85
- @puppet_dev_fetched = true
86
- return if reset_result[:exit_code].zero?
87
-
88
- PDK.logger.error reset_result[:stdout]
89
- PDK.logger.error reset_result[:stderr]
90
- raise PDK::CLI::FatalError, _("Unable to update git repository at '%{cachedir}'.") % { repo: puppet_dev_path }
91
- end
92
-
93
- def find_gem_for(version_str)
94
- version = parse_specified_version(version_str)
95
-
96
- # Look for a gem matching exactly the version passed in.
97
- if version.segments.length == 3
98
- exact_match_gem = find_gem(Gem::Requirement.create(version))
99
- return exact_match_gem unless exact_match_gem.nil?
100
- end
101
-
102
- # Construct a pessimistic version constraint to find the latest
103
- # available gem matching the level of specificity of version_str.
104
- requirement_string = version.approximate_recommendation
105
- requirement_string += '.0' unless version.segments.length == 1
106
- latest_requirement = Gem::Requirement.create(requirement_string)
107
-
108
- latest_available_gem = find_gem(latest_requirement)
109
-
110
- if latest_available_gem.nil?
111
- raise ArgumentError, _('Unable to find a Puppet gem matching %{requirement}.') % {
112
- requirement: latest_requirement,
113
- }
114
- end
115
-
116
- # Only issue this warning if they requested an exact version that isn't available.
117
- if version.segments.length == 3
118
- PDK.logger.warn(_('Puppet %{requested_version} is not available, activating %{found_version} instead.') % {
119
- requested_version: version_str,
120
- found_version: latest_available_gem[:gem_version].version,
121
- })
122
- end
123
-
124
- latest_available_gem
125
- end
126
-
127
- def from_pe_version(version_str)
128
- version = parse_specified_version(version_str)
129
-
130
- gem_version = pe_version_map.find do |version_map|
131
- version_map[:requirement].satisfied_by?(version)
132
- end
133
-
134
- if gem_version.nil?
135
- raise ArgumentError, _('Unable to map Puppet Enterprise version %{pe_version} to a Puppet version.') % {
136
- pe_version: version_str,
137
- }
138
- end
139
-
140
- PDK.logger.info _('Puppet Enterprise %{pe_version} maps to Puppet %{puppet_version}.') % {
141
- pe_version: version_str,
142
- puppet_version: gem_version[:gem_version],
143
- }
144
-
145
- find_gem_for(gem_version[:gem_version])
146
- end
147
-
148
- def from_module_metadata(metadata = nil)
149
- require 'pdk/module/metadata'
150
- require 'pdk/util'
151
-
152
- if metadata.nil?
153
- metadata_file = PDK::Util.find_upwards('metadata.json')
154
-
155
- unless metadata_file
156
- PDK.logger.warn _('Unable to determine Puppet version for module: no metadata.json present in module.')
157
- return
158
- end
159
-
160
- metadata = PDK::Module::Metadata.from_file(metadata_file)
161
- end
162
-
163
- metadata.validate_puppet_version_requirement!
164
- metadata_requirement = metadata.puppet_requirement
165
-
166
- # Split combined requirements like ">= 4.7.0 < 6.0.0" into their
167
- # component requirements [">= 4.7.0", "< 6.0.0"]
168
- pattern = %r{#{Gem::Requirement::PATTERN_RAW}}
169
- requirement_strings = metadata_requirement['version_requirement'].scan(pattern).map do |req|
170
- req.compact.join(' ')
171
- end
172
-
173
- gem_requirement = Gem::Requirement.create(requirement_strings)
174
- find_gem(gem_requirement)
175
- end
176
-
177
- private
178
-
179
- def parse_specified_version(version_str)
180
- Gem::Version.new(version_str)
181
- rescue ArgumentError
182
- raise ArgumentError, _('%{version} is not a valid version number.') % {
183
- version: version_str,
184
- }
185
- end
186
-
187
- def pe_version_map
188
- @pe_version_map ||= fetch_pe_version_map.map { |version_map|
189
- maps = version_map['versions'].map do |pe_release|
190
- requirements = ["= #{pe_release['version']}"]
191
-
192
- # Some PE release have a .0 Z release, which causes problems when
193
- # the user specifies "X.Y" expecting to get the latest Z and
194
- # instead getting the oldest.
195
- requirements << "!= #{pe_release['version'].gsub(%r{\.\d+\Z}, '')}" if pe_release['version'].end_with?('.0')
196
- {
197
- requirement: Gem::Requirement.create(requirements),
198
- gem_version: pe_release['puppet'],
199
- }
200
- end
201
-
202
- maps << {
203
- requirement: requirement_from_forge_range(version_map['release']),
204
- gem_version: version_map['versions'].find { |r| r['version'] == version_map['latest'] }['puppet'],
205
- }
206
- }.flatten
207
- end
208
-
209
- def fetch_pe_version_map
210
- require 'pdk/util/vendored_file'
211
-
212
- map = PDK::Util::VendoredFile.new('pe_versions.json', PE_VERSIONS_URL).read
213
-
214
- JSON.parse(map)
215
- rescue PDK::Util::VendoredFile::DownloadError => e
216
- raise PDK::CLI::FatalError, e.message
217
- rescue JSON::ParserError
218
- raise PDK::CLI::FatalError, _('Failed to parse Puppet Enterprise version map file.')
219
- end
220
-
221
- def requirement_from_forge_range(range_str)
222
- Gem::Requirement.create("~> #{range_str.gsub(%r{\.x\Z}, '.0')}")
223
- end
224
-
225
- def rubygems_puppet_versions
226
- @rubygems_puppet_versions ||= begin
227
- fetcher = Gem::SpecFetcher.fetcher
228
- puppet_tuples = fetcher.detect(:released) do |spec_tuple|
229
- spec_tuple.name == 'puppet' && Gem::Platform.match(spec_tuple.platform)
230
- end
231
- puppet_versions = puppet_tuples.map { |name, _| name.version }.uniq
232
- puppet_versions.sort { |a, b| b <=> a }
233
- end
234
- end
235
-
236
- def find_gem(requirement)
237
- require 'pdk/util'
238
-
239
- if PDK::Util.package_install?
240
- find_in_package_cache(requirement)
241
- else
242
- find_in_rubygems(requirement)
243
- end
244
- end
245
-
246
- def find_in_rubygems(requirement)
247
- require 'pdk/util/ruby_version'
248
-
249
- version = rubygems_puppet_versions.find { |r| requirement.satisfied_by?(r) }
250
- version.nil? ? nil : { gem_version: version, ruby_version: PDK::Util::RubyVersion.default_ruby_version }
251
- end
252
-
253
- def find_in_package_cache(requirement)
254
- require 'pdk/util/ruby_version'
255
-
256
- PDK::Util::RubyVersion.versions.each do |ruby_version, _|
257
- PDK::Util::RubyVersion.use(ruby_version)
258
- version = PDK::Util::RubyVersion.available_puppet_versions.find { |r| requirement.satisfied_by?(r) }
259
- return { gem_version: version, ruby_version: ruby_version } unless version.nil?
260
- end
261
-
262
- nil
263
- end
264
- end
265
- end
266
- end
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Util
5
+ class PuppetVersion
6
+ class << self
7
+ extend Forwardable
8
+
9
+ def_delegators :instance, :puppet_dev_env, :puppet_dev_path, :fetch_puppet_dev, :find_gem_for, :from_pe_version, :from_module_metadata, :latest_available
10
+
11
+ attr_writer :instance
12
+
13
+ def instance
14
+ @instance ||= new
15
+ end
16
+ end
17
+
18
+ PE_VERSIONS_URL = 'https://forgeapi.puppet.com/private/versions/pe'.freeze
19
+ DEFAULT_PUPPET_DEV_URL = 'https://github.com/puppetlabs/puppet'.freeze
20
+ DEFAULT_PUPPET_DEV_BRANCH = 'main'.freeze
21
+
22
+ def puppet_dev_env
23
+ require 'pdk/util/ruby_version'
24
+
25
+ {
26
+ gem_version: 'file://%{path}' % { path: puppet_dev_path },
27
+ ruby_version: PDK::Util::RubyVersion.latest_ruby_version,
28
+ }
29
+ end
30
+
31
+ def puppet_dev_path
32
+ require 'pdk/util'
33
+
34
+ File.join(PDK::Util.cachedir, 'src', 'puppet')
35
+ end
36
+
37
+ def latest_available
38
+ latest = find_gem(Gem::Requirement.create('>= 0'))
39
+
40
+ if latest.nil?
41
+ raise ArgumentError, _('Unable to find a Puppet gem in current Ruby environment or from Rubygems.org.')
42
+ end
43
+
44
+ latest
45
+ end
46
+
47
+ def puppet_dev_fetched?
48
+ !@puppet_dev_fetched.nil?
49
+ end
50
+
51
+ def fetch_puppet_dev(options = {})
52
+ return if options[:run] == :once && puppet_dev_fetched?
53
+
54
+ require 'pdk/util/git'
55
+
56
+ # Check if the source is cloned and is a readable git repo
57
+ unless PDK::Util::Git.remote_repo? puppet_dev_path
58
+ # Check if the path has something in it already. Delete it and prepare for clone if so.
59
+ if PDK::Util::Filesystem.exist? puppet_dev_path
60
+ PDK::Util::Filesystem.delete(puppet_dev_path) if PDK::Util::Filesystem.file? puppet_dev_path
61
+ PDK::Util::Filesystem.rm_rf(puppet_dev_path) if PDK::Util::Filesystem.directory? puppet_dev_path
62
+ end
63
+
64
+ PDK::Util::Filesystem.mkdir_p puppet_dev_path
65
+ clone_result = PDK::Util::Git.git('clone', DEFAULT_PUPPET_DEV_URL, puppet_dev_path)
66
+ return if clone_result[:exit_code].zero?
67
+
68
+ PDK.logger.error clone_result[:stdout]
69
+ PDK.logger.error clone_result[:stderr]
70
+ raise PDK::CLI::FatalError, _("Unable to clone git repository from '%{repo}'.") % { repo: DEFAULT_PUPPET_DEV_URL }
71
+ end
72
+
73
+ # Fetch Updates from remote repository
74
+ fetch_result = PDK::Util::Git.git('-C', puppet_dev_path, 'fetch', 'origin')
75
+
76
+ unless fetch_result[:exit_code].zero?
77
+ PDK.logger.error fetch_result[:stdout]
78
+ PDK.logger.error fetch_result[:stderr]
79
+ raise PDK::CLI::FatalError, _("Unable to fetch from git remote at '%{repo}'.") % { repo: DEFAULT_PUPPET_DEV_URL }
80
+ end
81
+
82
+ # Reset local repo to latest
83
+ reset_result = PDK::Util::Git.git('-C', puppet_dev_path, 'reset', '--hard', "origin/#{DEFAULT_PUPPET_DEV_BRANCH}")
84
+
85
+ @puppet_dev_fetched = true
86
+ return if reset_result[:exit_code].zero?
87
+
88
+ PDK.logger.error reset_result[:stdout]
89
+ PDK.logger.error reset_result[:stderr]
90
+ raise PDK::CLI::FatalError, _("Unable to update git repository at '%{cachedir}'.") % { repo: puppet_dev_path }
91
+ end
92
+
93
+ def find_gem_for(version_str)
94
+ version = parse_specified_version(version_str)
95
+
96
+ # Look for a gem matching exactly the version passed in.
97
+ if version.segments.length == 3
98
+ exact_match_gem = find_gem(Gem::Requirement.create(version))
99
+ return exact_match_gem unless exact_match_gem.nil?
100
+ end
101
+
102
+ # Construct a pessimistic version constraint to find the latest
103
+ # available gem matching the level of specificity of version_str.
104
+ requirement_string = version.approximate_recommendation
105
+ requirement_string += '.0' unless version.segments.length == 1
106
+ latest_requirement = Gem::Requirement.create(requirement_string)
107
+
108
+ latest_available_gem = find_gem(latest_requirement)
109
+
110
+ if latest_available_gem.nil?
111
+ raise ArgumentError, _('Unable to find a Puppet gem matching %{requirement}.') % {
112
+ requirement: latest_requirement,
113
+ }
114
+ end
115
+
116
+ # Only issue this warning if they requested an exact version that isn't available.
117
+ if version.segments.length == 3
118
+ PDK.logger.warn(_('Puppet %{requested_version} is not available, activating %{found_version} instead.') % {
119
+ requested_version: version_str,
120
+ found_version: latest_available_gem[:gem_version].version,
121
+ })
122
+ end
123
+
124
+ latest_available_gem
125
+ end
126
+
127
+ def from_pe_version(version_str)
128
+ version = parse_specified_version(version_str)
129
+
130
+ gem_version = pe_version_map.find do |version_map|
131
+ version_map[:requirement].satisfied_by?(version)
132
+ end
133
+
134
+ if gem_version.nil?
135
+ raise ArgumentError, _('Unable to map Puppet Enterprise version %{pe_version} to a Puppet version.') % {
136
+ pe_version: version_str,
137
+ }
138
+ end
139
+
140
+ PDK.logger.info _('Puppet Enterprise %{pe_version} maps to Puppet %{puppet_version}.') % {
141
+ pe_version: version_str,
142
+ puppet_version: gem_version[:gem_version],
143
+ }
144
+
145
+ find_gem_for(gem_version[:gem_version])
146
+ end
147
+
148
+ def from_module_metadata(metadata = nil)
149
+ require 'pdk/module/metadata'
150
+ require 'pdk/util'
151
+
152
+ if metadata.nil?
153
+ metadata_file = PDK::Util.find_upwards('metadata.json')
154
+
155
+ unless metadata_file
156
+ PDK.logger.warn _('Unable to determine Puppet version for module: no metadata.json present in module.')
157
+ return
158
+ end
159
+
160
+ metadata = PDK::Module::Metadata.from_file(metadata_file)
161
+ end
162
+
163
+ metadata.validate_puppet_version_requirement!
164
+ metadata_requirement = metadata.puppet_requirement
165
+
166
+ # Split combined requirements like ">= 4.7.0 < 6.0.0" into their
167
+ # component requirements [">= 4.7.0", "< 6.0.0"]
168
+ pattern = %r{#{Gem::Requirement::PATTERN_RAW}}
169
+ requirement_strings = metadata_requirement['version_requirement'].scan(pattern).map do |req|
170
+ req.compact.join(' ')
171
+ end
172
+
173
+ gem_requirement = Gem::Requirement.create(requirement_strings)
174
+ find_gem(gem_requirement)
175
+ end
176
+
177
+ private
178
+
179
+ def parse_specified_version(version_str)
180
+ Gem::Version.new(version_str)
181
+ rescue ArgumentError
182
+ raise ArgumentError, _('%{version} is not a valid version number.') % {
183
+ version: version_str,
184
+ }
185
+ end
186
+
187
+ def pe_version_map
188
+ @pe_version_map ||= fetch_pe_version_map.map { |version_map|
189
+ maps = version_map['versions'].map do |pe_release|
190
+ requirements = ["= #{pe_release['version']}"]
191
+
192
+ # Some PE release have a .0 Z release, which causes problems when
193
+ # the user specifies "X.Y" expecting to get the latest Z and
194
+ # instead getting the oldest.
195
+ requirements << "!= #{pe_release['version'].gsub(%r{\.\d+\Z}, '')}" if pe_release['version'].end_with?('.0')
196
+ {
197
+ requirement: Gem::Requirement.create(requirements),
198
+ gem_version: pe_release['puppet'],
199
+ }
200
+ end
201
+
202
+ maps << {
203
+ requirement: requirement_from_forge_range(version_map['release']),
204
+ gem_version: version_map['versions'].find { |r| r['version'] == version_map['latest'] }['puppet'],
205
+ }
206
+ }.flatten
207
+ end
208
+
209
+ def fetch_pe_version_map
210
+ require 'pdk/util/vendored_file'
211
+
212
+ map = PDK::Util::VendoredFile.new('pe_versions.json', PE_VERSIONS_URL).read
213
+
214
+ JSON.parse(map)
215
+ rescue PDK::Util::VendoredFile::DownloadError => e
216
+ raise PDK::CLI::FatalError, e.message
217
+ rescue JSON::ParserError
218
+ raise PDK::CLI::FatalError, _('Failed to parse Puppet Enterprise version map file.')
219
+ end
220
+
221
+ def requirement_from_forge_range(range_str)
222
+ Gem::Requirement.create("~> #{range_str.gsub(%r{\.x\Z}, '.0')}")
223
+ end
224
+
225
+ def rubygems_puppet_versions
226
+ @rubygems_puppet_versions ||= begin
227
+ fetcher = Gem::SpecFetcher.fetcher
228
+ puppet_tuples = fetcher.detect(:released) do |spec_tuple|
229
+ spec_tuple.name == 'puppet' && Gem::Platform.match(spec_tuple.platform)
230
+ end
231
+ puppet_versions = puppet_tuples.map { |name, _| name.version }.uniq
232
+ puppet_versions.sort { |a, b| b <=> a }
233
+ end
234
+ end
235
+
236
+ def find_gem(requirement)
237
+ require 'pdk/util'
238
+
239
+ if PDK::Util.package_install?
240
+ find_in_package_cache(requirement)
241
+ else
242
+ find_in_rubygems(requirement)
243
+ end
244
+ end
245
+
246
+ def find_in_rubygems(requirement)
247
+ require 'pdk/util/ruby_version'
248
+
249
+ version = rubygems_puppet_versions.find { |r| requirement.satisfied_by?(r) }
250
+ version.nil? ? nil : { gem_version: version, ruby_version: PDK::Util::RubyVersion.default_ruby_version }
251
+ end
252
+
253
+ def find_in_package_cache(requirement)
254
+ require 'pdk/util/ruby_version'
255
+
256
+ PDK::Util::RubyVersion.versions.each do |ruby_version, _|
257
+ PDK::Util::RubyVersion.use(ruby_version)
258
+ version = PDK::Util::RubyVersion.available_puppet_versions.find { |r| requirement.satisfied_by?(r) }
259
+ return { gem_version: version, ruby_version: ruby_version } unless version.nil?
260
+ end
261
+
262
+ nil
263
+ end
264
+ end
265
+ end
266
+ end