pdk 1.9.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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,87 +1,86 @@
1
- require 'json'
2
- require 'pdk/util/filesystem'
1
+ require 'pdk'
3
2
 
4
3
  module PDK
5
4
  module Module
6
5
  class Metadata
7
6
  attr_accessor :data
8
7
 
9
- include PDK::Util::Filesystem
10
-
11
8
  OPERATING_SYSTEMS = {
12
9
  'RedHat based Linux' => [
13
10
  {
14
- 'operatingsystem' => 'CentOS',
15
- 'operatingsystemrelease' => ['7'],
11
+ 'operatingsystem' => 'CentOS',
12
+ 'operatingsystemrelease' => ['7']
16
13
  },
17
14
  {
18
- 'operatingsystem' => 'OracleLinux',
19
- 'operatingsystemrelease' => ['7'],
15
+ 'operatingsystem' => 'OracleLinux',
16
+ 'operatingsystemrelease' => ['7']
20
17
  },
21
18
  {
22
- 'operatingsystem' => 'RedHat',
23
- 'operatingsystemrelease' => ['7'],
19
+ 'operatingsystem' => 'RedHat',
20
+ 'operatingsystemrelease' => ['8']
24
21
  },
25
22
  {
26
- 'operatingsystem' => 'Scientific',
27
- 'operatingsystemrelease' => ['7'],
28
- },
23
+ 'operatingsystem' => 'Scientific',
24
+ 'operatingsystemrelease' => ['7']
25
+ }
29
26
  ],
30
27
  'Debian based Linux' => [
31
28
  {
32
- 'operatingsystem' => 'Debian',
33
- 'operatingsystemrelease' => ['8'],
29
+ 'operatingsystem' => 'Debian',
30
+ 'operatingsystemrelease' => ['10']
34
31
  },
35
32
  {
36
- 'operatingsystem' => 'Ubuntu',
37
- 'operatingsystemrelease' => ['16.04'],
38
- },
33
+ 'operatingsystem' => 'Ubuntu',
34
+ 'operatingsystemrelease' => ['18.04']
35
+ }
39
36
  ],
40
37
  'Fedora' => {
41
- 'operatingsystem' => 'Fedora',
42
- 'operatingsystemrelease' => ['25'],
38
+ 'operatingsystem' => 'Fedora',
39
+ 'operatingsystemrelease' => ['29']
43
40
  },
44
41
  'OSX' => {
45
- 'operatingsystem' => 'Darwin',
46
- 'operatingsystemrelease' => ['16'],
42
+ 'operatingsystem' => 'Darwin',
43
+ 'operatingsystemrelease' => ['16']
47
44
  },
48
45
  'SLES' => {
49
- 'operatingsystem' => 'SLES',
50
- 'operatingsystemrelease' => ['12'],
46
+ 'operatingsystem' => 'SLES',
47
+ 'operatingsystemrelease' => ['15']
51
48
  },
52
49
  'Solaris' => {
53
- 'operatingsystem' => 'Solaris',
54
- 'operatingsystemrelease' => ['11'],
50
+ 'operatingsystem' => 'Solaris',
51
+ 'operatingsystemrelease' => ['11']
55
52
  },
56
53
  'Windows' => {
57
- 'operatingsystem' => 'windows',
58
- 'operatingsystemrelease' => ['2008 R2', '2012 R2', '10'],
54
+ 'operatingsystem' => 'windows',
55
+ 'operatingsystemrelease' => ['2019', '10']
59
56
  },
57
+ 'AIX' => {
58
+ 'operatingsystem' => 'AIX',
59
+ 'operatingsystemrelease' => ['6.1', '7.1', '7.2']
60
+ }
60
61
  }.freeze
61
62
 
62
63
  DEFAULT_OPERATING_SYSTEMS = [
63
64
  'RedHat based Linux',
64
65
  'Debian based Linux',
65
- 'Windows',
66
+ 'Windows'
66
67
  ].freeze
67
68
 
68
69
  DEFAULTS = {
69
- 'name' => nil,
70
- 'version' => '0.1.0',
71
- 'author' => nil,
72
- 'summary' => '',
73
- 'license' => 'Apache-2.0',
74
- 'source' => '',
75
- 'project_page' => nil,
76
- 'issues_url' => nil,
77
- 'dependencies' => [],
70
+ 'name' => nil,
71
+ 'version' => '0.1.0',
72
+ 'author' => nil,
73
+ 'summary' => '',
74
+ 'license' => 'Apache-2.0',
75
+ 'source' => '',
76
+ 'project_page' => nil,
77
+ 'issues_url' => nil,
78
+ 'dependencies' => [],
78
79
  'data_provider' => nil,
79
- 'operatingsystem_support' => DEFAULT_OPERATING_SYSTEMS.map { |os_name|
80
- OPERATING_SYSTEMS[os_name]
81
- }.flatten,
80
+ 'operatingsystem_support' => DEFAULT_OPERATING_SYSTEMS.dup,
82
81
  'requirements' => [
83
- { 'name' => 'puppet', 'version_requirement' => '>= 4.10.0 < 7.0.0' },
84
- ],
82
+ { 'name' => 'puppet', 'version_requirement' => '>= 7.24 < 9.0.0' }
83
+ ]
85
84
  }.freeze
86
85
 
87
86
  def initialize(params = {})
@@ -90,24 +89,21 @@ module PDK
90
89
  end
91
90
 
92
91
  def self.from_file(metadata_json_path)
93
- if metadata_json_path.nil?
94
- raise ArgumentError, _('Cannot read metadata from file: no path to file was given.')
95
- end
92
+ raise ArgumentError, 'Cannot read metadata from file: no path to file was given.' if metadata_json_path.nil?
96
93
 
97
- unless File.file?(metadata_json_path)
98
- raise ArgumentError, _("'%{file}' does not exist or is not a file.") % { file: metadata_json_path }
99
- end
94
+ raise ArgumentError, format("'%{file}' does not exist or is not a file.", file: metadata_json_path) unless PDK::Util::Filesystem.file?(metadata_json_path)
100
95
 
101
- unless File.readable?(metadata_json_path)
102
- raise ArgumentError, _("Unable to open '%{file}' for reading.") % { file: metadata_json_path }
103
- end
96
+ raise ArgumentError, format("Unable to open '%{file}' for reading.", file: metadata_json_path) unless PDK::Util::Filesystem.readable?(metadata_json_path)
104
97
 
98
+ require 'json'
105
99
  begin
106
- data = JSON.parse(File.read(metadata_json_path))
100
+ data = JSON.parse(PDK::Util::Filesystem.read_file(metadata_json_path))
107
101
  rescue JSON::JSONError => e
108
- raise ArgumentError, _('Invalid JSON in metadata.json: %{msg}') % { msg: e.message }
102
+ raise ArgumentError, format('Invalid JSON in metadata.json: %{msg}', msg: e.message)
109
103
  end
110
104
 
105
+ require 'pdk/util'
106
+ data['template-url'] = PDK::Util::TemplateURI.default_template_uri.metadata_format if PDK::Util.package_install? && data['template-url'] == PDK::Util::TemplateURI::PACKAGED_TEMPLATE_KEYWORD
111
107
  new(data)
112
108
  end
113
109
 
@@ -118,12 +114,14 @@ module PDK
118
114
  self
119
115
  end
120
116
 
121
- def to_json
117
+ def to_json(*_args)
118
+ require 'json'
119
+
122
120
  JSON.pretty_generate(@data.dup.delete_if { |_key, value| value.nil? })
123
121
  end
124
122
 
125
123
  def write!(path)
126
- write_file(path, to_json)
124
+ PDK::Util::Filesystem.write_file(path, to_json)
127
125
  end
128
126
 
129
127
  def forge_ready?
@@ -131,14 +129,16 @@ module PDK
131
129
  end
132
130
 
133
131
  def interview_for_forge!
132
+ require 'pdk/generate/module'
133
+
134
134
  PDK::Generate::Module.module_interview(self, only_ask: missing_fields)
135
135
  end
136
136
 
137
137
  def validate_puppet_version_requirement!
138
138
  msgs = {
139
- no_reqs: _('Module metadata does not contain any requirements.'),
140
- no_puppet_req: _('Module metadata does not contain a "puppet" requirement.'),
141
- no_puppet_ver: _('The "puppet" requirement in module metadata does not specify a "version_requirement".'),
139
+ no_reqs: 'Module metadata does not contain any requirements.',
140
+ no_puppet_req: 'Module metadata does not contain a "puppet" requirement.',
141
+ no_puppet_ver: 'The "puppet" requirement in module metadata does not specify a "version_requirement".'
142
142
  }
143
143
 
144
144
  raise ArgumentError, msgs[:no_reqs] unless @data.key?('requirements')
@@ -153,40 +153,41 @@ module PDK
153
153
  end
154
154
  end
155
155
 
156
- private
157
-
158
156
  def missing_fields
159
- fields = DEFAULTS.keys - %w[data_provider requirements dependencies]
157
+ fields = DEFAULTS.keys - ['data_provider', 'requirements', 'dependencies']
160
158
  fields.select { |key| @data[key].nil? || @data[key].empty? }
161
159
  end
162
160
 
161
+ private
162
+
163
163
  # Do basic validation and parsing of the name parameter.
164
164
  def process_name(data)
165
165
  validate_name(data['name'])
166
- author, _modname = data['name'].split(%r{[-/]}, 2)
166
+ author, modname = data['name'].split(%r{[-/]}, 2)
167
+ data['name'] = [author, modname].join('-')
167
168
 
168
169
  data['author'] ||= author if @data['author'] == DEFAULTS['author']
169
170
  end
170
171
 
171
172
  # Validates that the given module name is both namespaced and well-formed.
172
173
  def validate_name(name)
173
- return if name =~ %r{\A[a-z0-9]+[-\/][a-z][a-z0-9_]*\Z}i
174
+ return if %r{\A[a-z0-9]+[-/][a-z][a-z0-9_]*\Z}i.match?(name)
174
175
 
175
176
  namespace, modname = name.split(%r{[-/]}, 2)
176
177
  modname = :namespace_missing if namespace == ''
177
178
 
178
179
  err = case modname
179
180
  when nil, '', :namespace_missing
180
- _('Field must be a dash-separated user name and module name.')
181
- when %r{[^a-z0-9_]}i
182
- _('Module name must contain only alphanumeric or underscore characters.')
183
- when %r{^[^a-z]}i
184
- _('Module name must begin with a letter.')
181
+ 'Field must be a dash-separated user name and module name.'
182
+ when /[^a-z0-9_]/i
183
+ 'Module name must contain only alphanumeric or underscore characters.'
184
+ when /^[^a-z]/i
185
+ 'Module name must begin with a letter.'
185
186
  else
186
- _('Namespace must contain only alphanumeric characters.')
187
+ 'Namespace must contain only alphanumeric characters.'
187
188
  end
188
189
 
189
- raise ArgumentError, _("Invalid 'name' field in metadata.json: %{err}") % { err: err }
190
+ raise ArgumentError, format("Invalid 'name' field in metadata.json: %{err}", err: err)
190
191
  end
191
192
  end
192
193
  end
@@ -0,0 +1,255 @@
1
+ require 'pdk'
2
+ require 'uri'
3
+
4
+ module PDK
5
+ module Module
6
+ class Release
7
+ def self.invoke(module_path, options = {})
8
+ new(module_path, options).run
9
+ end
10
+
11
+ attr_reader :options, :module_path
12
+
13
+ def initialize(module_path, options = {})
14
+ @options = options
15
+
16
+ # TODO: Currently the release process can ONLY be run if the working directory IS the module root. However, in the future
17
+ # this WILL change, so we have the API arguments for it, but only accept `nil` for the first parameter
18
+ raise PDK::CLI::ExitWithError, 'Running the release process outside of the working directory is not supported' unless module_path.nil?
19
+
20
+ if module_path.nil?
21
+ module_path = PDK::Util.module_root
22
+ raise PDK::CLI::ExitWithError, 'The module release process requires a valid module path' if module_path.nil?
23
+ end
24
+ raise PDK::CLI::ExitWithError, format('%{module_path} is not a valid module', module_path: module_path) unless PDK::Util.in_module_root?(module_path)
25
+
26
+ @module_path = module_path
27
+ end
28
+
29
+ def run
30
+ # Pre-release checks
31
+ unless force?
32
+ raise PDK::CLI::ExitWithError, 'The module is not PDK compatible' if requires_pdk_compatibility? && !pdk_compatible?
33
+ raise PDK::CLI::ExitWithError, 'The module is not Forge compatible' if requires_forge_compatibility? && !forge_compatible?
34
+ end
35
+
36
+ # Note that these checks are duplicated in the run_publish method, however it's a much better
37
+ # experience to fail early, than going through the whole process, only to error at the end knowing full well
38
+ # it'll fail anyway.
39
+ validate_publish_options!
40
+
41
+ run_validations(options) unless skip_validation?
42
+
43
+ PDK.logger.info format('Releasing %{module_name} - from version %{module_version}', module_name: module_metadata.data['name'], module_version: module_metadata.data['version'])
44
+
45
+ PDK::Util::ChangelogGenerator.generate_changelog unless skip_changelog?
46
+
47
+ # Calculate the new module version
48
+ new_version = specified_version
49
+ new_version = PDK::Util::ChangelogGenerator.compute_next_version(module_metadata.data['version']) if new_version.nil? && !skip_changelog?
50
+ new_version = module_metadata.data['version'] if new_version.nil?
51
+
52
+ if new_version != module_metadata.data['version']
53
+ PDK.logger.info format('Updating version to %{module_version}', module_version: new_version)
54
+
55
+ # Set the new version in metadata file
56
+ module_metadata.data['version'] = new_version
57
+ write_module_metadata!
58
+
59
+ # Update the changelog with the correct version
60
+ PDK::Util::ChangelogGenerator.generate_changelog unless skip_changelog?
61
+
62
+ # Check if the versions match
63
+ latest_version = PDK::Util::ChangelogGenerator.latest_version
64
+ if !latest_version && (new_version != latest_version)
65
+ raise PDK::CLI::ExitWithError, format('%{new_version} does not match %{latest_version}', new_version: new_version, latest_version: latest_version)
66
+ end
67
+ end
68
+
69
+ run_documentation(options) unless skip_documentation?
70
+
71
+ run_dependency_checker(options) unless skip_dependency?
72
+
73
+ if skip_build?
74
+ # Even if we're skipping the build, we still need the name of the tarball
75
+ # Use the specified package path if set
76
+ package_file = specified_package if package_file.nil?
77
+ # Use the default as a last resort
78
+ package_file = default_package_filename if package_file.nil?
79
+ else
80
+ package_file = run_build(options)
81
+ end
82
+
83
+ run_publish(options.dup, package_file) unless skip_publish?
84
+ end
85
+
86
+ def module_metadata
87
+ @module_metada ||= PDK::Module::Metadata.from_file(File.join(module_path, 'metadata.json'))
88
+ end
89
+
90
+ def write_module_metadata!
91
+ module_metadata.write!(File.join(module_path, 'metadata.json'))
92
+ clear_cached_data
93
+ end
94
+
95
+ def default_package_filename
96
+ return @default_tarball_filename unless @default_tarball_filename.nil?
97
+
98
+ builder = PDK::Module::Build.new(module_dir: module_path)
99
+ @default_tarball_filename = builder.package_file
100
+ end
101
+
102
+ def run_validations(opts)
103
+ # TODO: Surely I can use a pre-existing class for this?
104
+ PDK::CLI::Util.validate_puppet_version_opts(opts)
105
+
106
+ PDK::CLI::Util.module_version_check
107
+
108
+ puppet_env = PDK::CLI::Util.puppet_from_opts_or_env(opts)
109
+ PDK::Util::PuppetVersion.fetch_puppet_dev if opts[:'puppet-dev']
110
+ PDK::Util::RubyVersion.use(puppet_env[:ruby_version])
111
+
112
+ PDK::Util::Bundler.ensure_bundle!(puppet_env[:gemset])
113
+
114
+ validator_exit_code, = PDK::Validate.invoke_validators_by_name(PDK.context, PDK::Validate.validator_names, false, options)
115
+ raise PDK::CLI::ExitWithError, 'An error occured during validation' unless validator_exit_code.zero?
116
+ end
117
+
118
+ def run_documentation(_opts)
119
+ PDK.logger.info 'Updating documentation using puppet strings'
120
+ docs_command = PDK::CLI::Exec::InteractiveCommand.new(PDK::CLI::Exec.bundle_bin, 'exec', 'puppet', 'strings', 'generate', '--format', 'markdown', '--out', 'REFERENCE.md')
121
+ docs_command.context = :module
122
+ result = docs_command.execute!
123
+ raise PDK::CLI::ExitWithError, format('An error occured generating the module documentation: %{stdout}', stdout: result[:stdout]) unless result[:exit_code].zero?
124
+ end
125
+
126
+ def run_dependency_checker(_opts)
127
+ # run dependency-checker and output dependent modules list
128
+ PDK.logger.info 'Running dependency checks'
129
+
130
+ dep_command = PDK::CLI::Exec::Command.new('dependency-checker', 'metadata.json')
131
+ dep_command.context = :module
132
+ result = dep_command.execute!
133
+
134
+ raise PDK::CLI::ExitWithError, format('An error occured checking the module dependencies: %{stdout}', stdout: result[:stdout]) unless result[:exit_code].zero?
135
+ end
136
+
137
+ # @return [String] Path to the built tarball
138
+ def run_build(opts)
139
+ PDK::Module::Build.invoke(opts.dup)
140
+ end
141
+
142
+ def run_publish(_opts, tarball_path)
143
+ validate_publish_options!
144
+ raise PDK::CLI::ExitWithError, format('Module tarball %{tarball_path} does not exist', tarball_path: tarball_path) unless PDK::Util::Filesystem.file?(tarball_path)
145
+
146
+ # TODO: Replace this code when the upload functionality is added to the forge ruby gem
147
+ require 'base64'
148
+ file_data = Base64.encode64(PDK::Util::Filesystem.read_file(tarball_path, open_args: 'rb'))
149
+
150
+ PDK.logger.info 'Uploading tarball to puppet forge...'
151
+ uri = URI(forge_upload_url)
152
+ require 'net/http'
153
+ request = Net::HTTP::Post.new(uri.path)
154
+ request['Authorization'] = "Bearer #{forge_token}"
155
+ request['Content-Type'] = 'application/json'
156
+ data = { file: file_data }
157
+
158
+ request.body = data.to_json
159
+
160
+ require 'openssl'
161
+ use_ssl = uri.instance_of?(URI::HTTPS)
162
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: use_ssl) do |http|
163
+ http.request(request)
164
+ end
165
+
166
+ raise PDK::CLI::ExitWithError, format('Error uploading to Puppet Forge: %{result}', result: response.body) unless response.is_a?(Net::HTTPSuccess)
167
+
168
+ PDK.logger.info 'Publish to Forge was successful'
169
+ end
170
+
171
+ def validate_publish_options!
172
+ return if skip_publish?
173
+ raise PDK::CLI::ExitWithError, 'Missing forge-upload-url option' unless forge_upload_url
174
+ raise PDK::CLI::ExitWithError, 'Missing forge-token option' unless forge_token
175
+ end
176
+
177
+ def force?
178
+ options[:force]
179
+ end
180
+
181
+ def skip_build?
182
+ options[:'skip-build']
183
+ end
184
+
185
+ def skip_changelog?
186
+ options[:'skip-changelog']
187
+ end
188
+
189
+ def skip_dependency?
190
+ options[:'skip-dependency']
191
+ end
192
+
193
+ def skip_documentation?
194
+ options[:'skip-documentation']
195
+ end
196
+
197
+ def skip_publish?
198
+ options[:'skip-publish']
199
+ end
200
+
201
+ def skip_validation?
202
+ options[:'skip-validation']
203
+ end
204
+
205
+ def specified_version
206
+ options[:version]
207
+ end
208
+
209
+ def specified_package
210
+ options[:file]
211
+ end
212
+
213
+ def forge_token
214
+ options[:'forge-token']
215
+ end
216
+
217
+ def forge_upload_url
218
+ options[:'forge-upload-url']
219
+ end
220
+
221
+ def requires_pdk_compatibility?
222
+ # Validation, Changelog and Dependency checks require the
223
+ # module to be PDK Compatible
224
+ !(skip_validation? && skip_changelog? && skip_dependency?)
225
+ end
226
+
227
+ def requires_forge_compatibility?
228
+ # Pushing to the for requires the metadata to be forge compatible
229
+ !skip_publish?
230
+ end
231
+
232
+ # :nocov:
233
+ # These are just convenience methods and are tested elsewhere
234
+ def forge_compatible?
235
+ module_metadata.forge_ready?
236
+ end
237
+
238
+ def pdk_compatible?
239
+ return @pdk_compatible unless @pdk_compatible.nil?
240
+
241
+ builder = PDK::Module::Build.new(module_dir: module_path)
242
+ @pdk_compatible = builder.module_pdk_compatible?
243
+ end
244
+ # :nocov:
245
+
246
+ private
247
+
248
+ def clear_cached_data
249
+ @module_metadata = nil
250
+ @pdk_compatible = nil
251
+ @default_tarball_filename = nil
252
+ end
253
+ end
254
+ end
255
+ end
@@ -1,21 +1,19 @@
1
- require 'pdk/module/convert'
1
+ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Module
5
5
  class Update < Convert
6
- GIT_DESCRIBE_PATTERN = %r{\A(?<base>.+?)-(?<additional_commits>\d+)-g(?<sha>.+)\Z}
6
+ GIT_DESCRIBE_PATTERN = /\A(?<base>.+?)-(?<additional_commits>\d+)-g(?<sha>.+)\Z/.freeze
7
7
 
8
8
  def run
9
+ template_uri.uri_fragment = new_template_version
10
+
9
11
  stage_changes!
10
12
 
11
- if current_version == new_version
12
- PDK.logger.debug _('This module is already up to date with version %{version} of the template.') % {
13
- version: new_version,
14
- }
15
- end
13
+ PDK.logger.debug format('This module is already up to date with version %{version} of the template.', version: new_version) if current_version == new_version
16
14
 
17
15
  unless update_manager.changes?
18
- PDK::Report.default_target.puts(_('No changes required.'))
16
+ PDK::Report.default_target.puts('No changes required.')
19
17
  return
20
18
  end
21
19
 
@@ -27,31 +25,31 @@ module PDK
27
25
  return if noop?
28
26
 
29
27
  unless force?
30
- message = _('Do you want to continue and make these changes to your module?')
28
+ message = 'Do you want to continue and make these changes to your module?'
31
29
  return unless PDK::CLI::Util.prompt_for_yes(message)
32
30
  end
33
31
 
34
- # Remove these files straight away as these changes are not something that the user needs to review.
35
- if needs_bundle_update?
36
- update_manager.unlink_file('Gemfile.lock')
37
- update_manager.unlink_file(File.join('.bundle', 'config'))
38
- end
32
+ # Remove these files straight away as these changes are not something
33
+ # that the user needs to review.
34
+ update_manager.unlink_file('Gemfile.lock')
35
+ update_manager.unlink_file(File.join('.bundle', 'config'))
39
36
 
40
37
  update_manager.sync_changes!
41
38
 
42
- PDK::Util::Bundler.ensure_bundle! if needs_bundle_update?
39
+ require 'pdk/util/bundler'
40
+ PDK::Util::Bundler.ensure_bundle!
43
41
 
44
42
  print_result 'Update completed'
45
43
  end
46
44
 
47
45
  def module_metadata
48
- @module_metadata ||= PDK::Module::Metadata.from_file('metadata.json')
46
+ @module_metadata ||= PDK::Module::Metadata.from_file(File.join(module_dir, 'metadata.json'))
49
47
  rescue ArgumentError => e
50
48
  raise PDK::CLI::ExitWithError, e.message
51
49
  end
52
50
 
53
- def template_url
54
- @template_url ||= module_metadata.data['template-url']
51
+ def template_uri
52
+ @template_uri ||= PDK::Util::TemplateURI.new(module_metadata.data['template-url'])
55
53
  end
56
54
 
57
55
  def current_version
@@ -62,8 +60,30 @@ module PDK
62
60
  @new_version ||= fetch_remote_version(new_template_version)
63
61
  end
64
62
 
63
+ def new_template_version
64
+ return options[:'template-ref'] if options[:'template-ref']
65
+
66
+ if template_uri.default? && PDK::Util::Git.tag?(template_uri.bare_uri, template_uri.uri_fragment) && PDK::Util.package_install?
67
+ PDK::Util::TemplateURI.default_template_ref
68
+ else
69
+ template_uri.uri_fragment
70
+ end
71
+ end
72
+
73
+ def pinned_to_puppetlabs_template_tag?
74
+ return false unless template_uri.puppetlabs_template?
75
+ return false unless PDK::Util::Git.tag?(template_uri.bare_uri, template_uri.uri_fragment)
76
+ return false if latest_template?
77
+
78
+ template_uri.uri_fragment == new_template_version
79
+ end
80
+
65
81
  private
66
82
 
83
+ def latest_template?
84
+ [PDK::TEMPLATE_REF, 'master', 'main'].include?(template_uri.uri_fragment)
85
+ end
86
+
67
87
  def current_template_version
68
88
  @current_template_version ||= module_metadata.data['template-ref']
69
89
  end
@@ -73,38 +93,29 @@ module PDK
73
93
 
74
94
  return data if data.nil?
75
95
 
76
- if data[:base].start_with?('heads/')
77
- "#{data[:base].gsub(%r{^heads/}, '')}@#{data[:sha]}"
96
+ if %r{^(?:heads|remotes)/}.match?(data[:base])
97
+ "#{data[:base].gsub(%r{^(heads/|remotes/\w+?/)}, '')}@#{data[:sha]}"
78
98
  else
79
99
  data[:base]
80
100
  end
81
101
  end
82
102
 
83
- def new_template_version
84
- PDK::Util.default_template_ref
85
- end
86
-
87
- def fetch_remote_version(version)
88
- return version unless version.include?('/')
103
+ def fetch_remote_version(template_ref)
104
+ return template_ref unless current_template_version.is_a?(String)
105
+ return template_ref if template_ref == PDK::TEMPLATE_REF
89
106
 
90
- branch = version.partition('/').last
91
107
  sha_length = GIT_DESCRIBE_PATTERN.match(current_template_version)[:sha].length - 1
92
- "#{branch}@#{PDK::Util::Git.ls_remote(template_url, "refs/heads/#{branch}")[0..sha_length]}"
108
+ "#{template_ref}@#{PDK::Util::Git.ls_remote(template_uri.bare_uri, template_ref)[0..sha_length]}"
93
109
  end
94
110
 
95
111
  def update_message
96
- format_string = if template_url == PDK::Util.puppetlabs_template_url
97
- _('Updating %{module_name} using the default template, from %{current_version} to %{new_version}')
112
+ format_string = if template_uri.default?
113
+ 'Updating %{module_name} using the default template, from %{current_version} to %{new_version}'
98
114
  else
99
- _('Updating %{module_name} using the template at %{template_url}, from %{current_version} to %{new_version}')
115
+ 'Updating %{module_name} using the template at %{template_url}, from %{current_version} to %{new_version}'
100
116
  end
101
117
 
102
- format_string % {
103
- module_name: module_metadata.data['name'],
104
- template_url: template_url,
105
- current_version: current_version,
106
- new_version: new_version,
107
- }
118
+ format(format_string, module_name: module_metadata.data['name'], template_url: template_uri.bare_uri, current_version: current_version, new_version: new_version)
108
119
  end
109
120
  end
110
121
  end