pdk 2.1.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1329 -1292
  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 -283
  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 -192
  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 -42
  70. data/lib/pdk/config/yaml_with_schema.rb +59 -59
  71. data/lib/pdk/config.rb +390 -384
  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 -254
  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 -124
  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 -84
  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 -220
  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 +19 -13
@@ -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