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
@@ -0,0 +1,98 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Context
5
+ autoload :None, 'pdk/context/none'
6
+ autoload :Module, 'pdk/context/module'
7
+ autoload :ControlRepo, 'pdk/context/control_repo'
8
+
9
+ # Automatically determines the PDK Context given a path. Create will continue up the directory tree until it
10
+ # finds a valid context
11
+ # @return [PDK::Context::AbstractContext] Returns a PDK::Context::None if the context could not be determined
12
+ def self.create(context_path)
13
+ return PDK::Context::None.new(context_path) unless PDK::Util::Filesystem.directory?(context_path)
14
+
15
+ previous = nil
16
+ current = PDK::Util::Filesystem.expand_path(context_path)
17
+ until !PDK::Util::Filesystem.directory?(current) || current == previous
18
+ # Control Repo detection
19
+ return PDK::Context::ControlRepo.new(current, context_path) if PDK.feature_flag?('controlrepo') && PDK::ControlRepo.control_repo_root?(current)
20
+
21
+ # Puppet Module detection
22
+ metadata_file = File.join(current, 'metadata.json')
23
+ return PDK::Context::Module.new(current, context_path) if PDK::Util::Filesystem.file?(metadata_file) || PDK::Util.in_module_root?(context_path)
24
+
25
+ previous = current
26
+ current = PDK::Util::Filesystem.expand_path('..', current)
27
+ end
28
+ PDK::Context::None.new(context_path)
29
+ end
30
+
31
+ # Abstract class which all PDK Contexts will subclass from.
32
+ # @abstract
33
+ class AbstractContext
34
+ # The root of this context, for example the module root when inside a module. This can be different from context_path
35
+ # For example a Module context_path could be /path/to/module/manifests/ but the root_path will be /path/to/module as
36
+ # that is the root of the Module context. Defaults to the context_path if not set.
37
+ # @return [String]
38
+ def root_path
39
+ @root_path || @context_path
40
+ end
41
+
42
+ # The path used to create this context, for example the current working directory. This can be different from root_path
43
+ # For example a Module context_path could be /path/to/module/manifests/ but the root_path will be /path/to/module as
44
+ # that is the root of the Module context
45
+ # @return [String]
46
+ attr_reader :context_path
47
+
48
+ # @param context_path [String] The path where this context was created from e.g. Dir.pwd
49
+ def initialize(context_path)
50
+ @context_path = context_path
51
+ @root_path = nil
52
+ end
53
+
54
+ # Whether the current context is compatible with the PDK e.g. in a Module context, whether it has the correct metadata.json content
55
+ # @return [Boolean] Default is not compatible
56
+ def pdk_compatible?
57
+ false
58
+ end
59
+
60
+ # The friendly name to display for this context
61
+ # @api private
62
+ # @abstract
63
+ def display_name; end
64
+
65
+ # The context which this context is in. For example a Module Context (/controlrepo/site/profile) can be inside of a Control Repo context (/controlrepo)
66
+ # The default is to search in the parent directory of this context
67
+ # @return [PDK::Context::AbstractContext, Nil] Returns the parent context or nil if there is no parent.
68
+ def parent_context
69
+ # Default detection is just look for the context in the parent directory of this context
70
+ @parent_context || PDK::Context.create(File.dirname(root_path))
71
+ end
72
+
73
+ # Writes the current context information, and parent contexts, to the PDK Debug Logger.
74
+ # This is mainly used by the PDK CLI when in debug mode to assist users to figure out why the PDK is misbehaving.
75
+ # @api private
76
+ def to_debug_log
77
+ current = self
78
+ depth = 1
79
+ loop do
80
+ PDK.logger.debug("Detected #{current.display_name} at #{current.root_path.nil? ? current.context_path : current.root_path}")
81
+ current = current.parent_context
82
+ break if current.nil?
83
+
84
+ depth += 1
85
+ # Circuit breaker in case there are circular references
86
+ break if depth > 20
87
+ end
88
+ nil
89
+ end
90
+
91
+ # :nocov: There's nothing to test here
92
+ def to_s
93
+ "#<#{self.class}:#{object_id}>#{context_path}"
94
+ end
95
+ # :nocov:
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,89 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module ControlRepo
5
+ CONTROL_REPO_FILES = ['environment.conf', 'Puppetfile'].freeze
6
+
7
+ DEFAULT_IGNORED = [
8
+ '/pkg/',
9
+ '~*',
10
+ '/coverage',
11
+ # Strictly speaking this isn't default but if people have tricked older PDK into thinking that a
12
+ # Control Repo is a module, they may have recursive symlinks in spec/fixtures/modules
13
+ '/spec/fixtures/modules/',
14
+ '/vendor/'
15
+ ].freeze
16
+
17
+ # Returns path to the root of the Control Repo being worked on.
18
+ #
19
+ # An environment.conf is required for a PDK compatible Control Repo,
20
+ # whereas Puppetfile is optional.
21
+ #
22
+ # Note - A Bolt Project can also be a Control Repo.
23
+ #
24
+ # Note - Non-Directory environments can exist however directory based
25
+ # environments are the supported/preferred way.
26
+ #
27
+ # @see https://puppet.com/docs/pe/latest/control_repo.html
28
+ #
29
+ # @param strict_check [Boolean] When strict_check is true, only return the path
30
+ # if the Control Repo is strictly _only_ a control repository. For example,
31
+ # not also a Puppet Bolt project directory Default is false.
32
+ #
33
+ # @return [String, nil] Fully qualified base path to Control Repo, or nil if
34
+ # the current working dir does not appear to be within a Control Repo.
35
+ def find_control_repo_root(strict_check = false)
36
+ environment_conf_path = PDK::Util.find_upwards('environment.conf')
37
+ path = if environment_conf_path
38
+ File.dirname(environment_conf_path)
39
+ elsif control_repo_root?(Dir.pwd)
40
+ Dir.pwd
41
+ end
42
+ return path if path.nil? || !strict_check
43
+
44
+ PDK::Bolt.bolt_project_root?(path) ? nil : path
45
+ end
46
+ module_function :find_control_repo_root
47
+
48
+ # Returns true or false depending on if any of the common files in a Control Repo
49
+ # are found in the specified directory. If a directory is not specified, the current
50
+ # working directory is used.
51
+ #
52
+ # @return [boolean] True if any folders from CONTROL_REPO_FILES are found in the current dir,
53
+ # false otherwise.
54
+ def control_repo_root?(path = Dir.pwd)
55
+ CONTROL_REPO_FILES.any? { |file| PDK::Util::Filesystem.file?(File.join(path, file)) }
56
+ end
57
+ module_function :control_repo_root?
58
+
59
+ # Returns a PDK::Config::Namespace for the specified environment.conf file.
60
+ # Note there is no validation of the path.
61
+ #
62
+ # @param path [String] The path to the environment.conf file
63
+ #
64
+ # @return [PDK::Config::IniFile] The configuration file
65
+ def environment_conf_as_config(path)
66
+ PDK::Config::IniFile.new('environment', file: path) do
67
+ setting :modulepath do
68
+ # As per https://puppet.com/docs/puppet/latest/config_file_environment.html#allowed-settings
69
+ default_to { 'modules:$basemodulepath' }
70
+ end
71
+
72
+ setting :manifest do
73
+ # As per https://puppet.com/docs/puppet/latest/config_file_environment.html#allowed-settings
74
+ default_to { 'manifests/' }
75
+ end
76
+ end
77
+ end
78
+ module_function :environment_conf_as_config
79
+
80
+ def default_ignored_pathspec(ignore_dotfiles = true)
81
+ require 'pathspec'
82
+
83
+ PathSpec.new(DEFAULT_IGNORED).tap do |ps|
84
+ ps.add('.*') if ignore_dotfiles
85
+ end
86
+ end
87
+ module_function :default_ignored_pathspec
88
+ end
89
+ end
@@ -1,48 +1,42 @@
1
- require 'pdk/generate/puppet_object'
1
+ require 'pdk'
2
2
 
3
3
  module PDK
4
4
  module Generate
5
5
  class DefinedType < PuppetObject
6
- OBJECT_TYPE = :defined_type
6
+ PUPPET_STRINGS_TYPE = 'defined_types'.freeze
7
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 = { name: object_name }
8
+ def initialize(*_args)
9
+ super
10
+ object_name_parts = @object_name.split('::')
15
11
 
16
- data
12
+ @object_name = if object_name_parts.first == module_name
13
+ object_name
14
+ else
15
+ [module_name, object_name].join('::')
16
+ end
17
17
  end
18
18
 
19
- # Calculates the path to the .pp file that the new defined type will be
20
- # written to.
21
- #
22
- # @return [String] the path where the new defined type will be written.
23
- def target_object_path
24
- @target_pp_path ||= begin
25
- define_name_parts = object_name.split('::')[1..-1]
26
- define_name_parts << 'init' if define_name_parts.empty?
27
-
28
- "#{File.join(module_dir, 'manifests', *define_name_parts)}.pp"
29
- end
19
+ def friendly_name
20
+ 'Defined Type'.freeze
30
21
  end
31
22
 
32
- # Calculates the path to the file where the tests for the new defined
33
- # type will be written.
34
- #
35
- # @return [String] the path where the tests for the new defined type
36
- # will be written.
37
- def target_spec_path
38
- @target_spec_path ||= begin
39
- define_name_parts = object_name.split('::')
23
+ def template_files
24
+ # Calculate the defined type tests name
25
+ define_name_parts = object_name.split('::')
26
+ # drop the module name if the object name contains multiple parts
27
+ define_name_parts.delete_at(0) if define_name_parts.length > 1
28
+ files = { 'defined_type_spec.erb' => "#{File.join('spec', 'defines', *define_name_parts)}_spec.rb" }
29
+ return files if spec_only?
30
+
31
+ define_name_parts = object_name.split('::')[1..]
32
+ define_name_parts << 'init' if define_name_parts.empty?
33
+ files['defined_type.erb'] = "#{File.join('manifests', *define_name_parts)}.pp"
40
34
 
41
- # drop the module name if the object name contains multiple parts
42
- define_name_parts.delete_at(0) if define_name_parts.length > 1
35
+ files
36
+ end
43
37
 
44
- "#{File.join(module_dir, 'spec', 'defines', *define_name_parts)}_spec.rb"
45
- end
38
+ def template_data
39
+ { name: object_name }
46
40
  end
47
41
  end
48
42
  end
@@ -0,0 +1,26 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Generate
5
+ class Fact < PuppetObject
6
+ def friendly_name
7
+ 'Custom Fact'.freeze
8
+ end
9
+
10
+ def template_files
11
+ files = {
12
+ 'fact_spec.erb' => "#{File.join('spec', 'unit', 'facter', object_name)}_spec.rb"
13
+ }
14
+ return files if spec_only?
15
+
16
+ files.merge(
17
+ 'fact.erb' => "#{File.join('lib', 'facter', object_name)}.rb"
18
+ )
19
+ end
20
+
21
+ def template_data
22
+ { name: object_name }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Generate
5
+ class Function < PuppetObject
6
+ def initialize(*_args)
7
+ super
8
+ object_name_parts = @object_name.split('::')
9
+
10
+ @object_name = if object_name_parts.first == module_name
11
+ object_name
12
+ else
13
+ [module_name, object_name].join('::')
14
+ end
15
+ end
16
+
17
+ def friendly_name
18
+ 'Function'.freeze
19
+ end
20
+
21
+ def template_files
22
+ # Calculate the function tests name
23
+ func_name_parts = object_name.split('::')
24
+ # Drop the module name if the object name contains multiple parts
25
+ func_name_parts.delete_at(0) if func_name_parts.length > 1
26
+ files = {
27
+ File.join('functions', 'function_spec.erb') => "#{File.join('spec', 'functions', *func_name_parts)}_spec.rb"
28
+ }
29
+ return files if spec_only?
30
+
31
+ func_name_parts = object_name.split('::')[1..]
32
+ template_file = File.join('functions', "#{options[:type]}_function.erb")
33
+
34
+ files[template_file] = if options[:type].eql?('v4')
35
+ "#{File.join('lib', 'puppet', 'functions', module_name, *func_name_parts)}.rb"
36
+ else
37
+ "#{File.join('functions', *func_name_parts)}.pp"
38
+ end
39
+ files
40
+ end
41
+
42
+ def template_data
43
+ func_name = object_name.split('::').last
44
+ namespace = object_name.split('::')[0...-1].join('::')
45
+ { name: object_name, func_name: func_name, namespace: namespace }
46
+ end
47
+ end
48
+ end
49
+ end