pdk 3.0.1 → 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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -1
  3. data/lib/pdk/cli/build.rb +0 -2
  4. data/lib/pdk/cli/bundle.rb +0 -2
  5. data/lib/pdk/cli/console.rb +0 -2
  6. data/lib/pdk/cli/convert.rb +3 -3
  7. data/lib/pdk/cli/env.rb +0 -2
  8. data/lib/pdk/cli/new/class.rb +0 -2
  9. data/lib/pdk/cli/new/defined_type.rb +0 -2
  10. data/lib/pdk/cli/new/fact.rb +0 -2
  11. data/lib/pdk/cli/new/function.rb +0 -2
  12. data/lib/pdk/cli/new/module.rb +0 -2
  13. data/lib/pdk/cli/new/provider.rb +0 -2
  14. data/lib/pdk/cli/new/task.rb +0 -2
  15. data/lib/pdk/cli/new/test.rb +0 -2
  16. data/lib/pdk/cli/release/prep.rb +0 -2
  17. data/lib/pdk/cli/release/publish.rb +0 -2
  18. data/lib/pdk/cli/release.rb +0 -8
  19. data/lib/pdk/cli/test/unit.rb +0 -2
  20. data/lib/pdk/cli/update.rb +3 -3
  21. data/lib/pdk/cli/util.rb +0 -38
  22. data/lib/pdk/cli/validate.rb +0 -7
  23. data/lib/pdk/cli.rb +0 -2
  24. data/lib/pdk/config/namespace.rb +3 -3
  25. data/lib/pdk/config/setting.rb +3 -3
  26. data/lib/pdk/config.rb +0 -80
  27. data/lib/pdk/module/convert.rb +7 -2
  28. data/lib/pdk/module/metadata.rb +1 -1
  29. data/lib/pdk/module/update_manager.rb +29 -3
  30. data/lib/pdk/report/event.rb +1 -1
  31. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +10 -13
  32. data/lib/pdk/template/renderer/v1/renderer.rb +3 -1
  33. data/lib/pdk/template.rb +0 -3
  34. data/lib/pdk/util/filesystem.rb +10 -0
  35. data/lib/pdk/version.rb +2 -2
  36. data/lib/pdk.rb +0 -14
  37. metadata +2 -49
  38. data/lib/pdk/analytics/client/google_analytics.rb +0 -141
  39. data/lib/pdk/analytics/client/noop.rb +0 -25
  40. data/lib/pdk/analytics/util.rb +0 -18
  41. data/lib/pdk/analytics.rb +0 -30
  42. data/lib/pdk/config/analytics_schema.json +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c39902d0ebbac37358fd3fccf5de760b47f77860054b08864ccdae63150b7597
4
- data.tar.gz: 6a4d8beb3013edf1ed946b9cf94cd90b055ad63500102e131734600c81c3a5a5
3
+ metadata.gz: 61c49c154cc69ce1e3c47ddfdd089b42c9c4c5e610bfb2e6caf3256939a16d5d
4
+ data.tar.gz: 420c70b35bfaf64077b990f6853bfc92062659fc7ba36379cb053232b99313a5
5
5
  SHA512:
6
- metadata.gz: 7af78ce8b0c4bb9122081a2c6449d862da04c9fec85d428b2e8ace3e88a74930fcf809462062b07994307c54c3ee5a827a83ae26e5c67b95f659c3f5c0cb89b5
7
- data.tar.gz: c5af71c375d94c9e22f4c7ae284213a39aaa87b8bc21980580ce4e79743979d4cbb967f330c775dcd2ebc4d3046c4c9c5080480172e07dec33afd9546b94da7e
6
+ metadata.gz: 3e2e8f1e63a936c310459a67a14b632e00a4ac1694fa4cc77f2849b3d19bf09cc9a5e4a19d7ce3e3a0eb6493a31141c76a72bc98d30cbb4eb7ffd1f5d3da7ca0
7
+ data.tar.gz: fe219a60e2cf9f7263e1b8fd8e721f143349aa3f03125649e551f9978ae3a9012c4b051f21b2707a266ed31a67772ad6c3cef026f1c5a1a0dadaf8257dc888dc
data/CHANGELOG.md CHANGED
@@ -5,7 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
 
6
6
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org).
7
7
 
8
- ## [v3.0.1](https://github.com/puppetlabs/pdk/tree/v3.0.1) - 2023-12-07
8
+ ## [v3.2.0](https://github.com/puppetlabs/pdk/tree/v3.2.0) - 2024-05-02
9
+
10
+ [Full Changelog](https://github.com/puppetlabs/pdk/compare/v3.1.0...v3.2.0)
11
+
12
+ ### Fixed
13
+
14
+ - (CAT-1807) Remove analytics from the PDK [#1339](https://github.com/puppetlabs/pdk/pull/1339) ([david22swan](https://github.com/david22swan))
15
+
16
+ ## [v3.1.0](https://github.com/puppetlabs/pdk/tree/v3.1.0) - 2024-04-11
17
+
18
+ [Full Changelog](https://github.com/puppetlabs/pdk/compare/v3.0.1...v3.1.0)
19
+
20
+ ### Added
21
+
22
+ - Allow `pdk convert` and `pdk update` to work in a ControlRepo context [#1310](https://github.com/puppetlabs/pdk/pull/1310) ([garrettrowell](https://github.com/garrettrowell))
23
+ - Support executable templates [#1289](https://github.com/puppetlabs/pdk/pull/1289) ([nabertrand](https://github.com/nabertrand))
24
+
25
+ ### Fixed
26
+
27
+ - (CAT-1796) Fix missing locale gem [#1337](https://github.com/puppetlabs/pdk/pull/1337) ([LukasAud](https://github.com/LukasAud))
28
+ - (CAT-1703) Convert concurrent-ruby from a pin to a pessimistic constraint [#1312](https://github.com/puppetlabs/pdk/pull/1312) ([david22swan](https://github.com/david22swan))
29
+
30
+ ## [v3.0.1](https://github.com/puppetlabs/pdk/tree/v3.0.1) - 2023-12-13
9
31
 
10
32
  [Full Changelog](https://github.com/puppetlabs/pdk/compare/v3.0.0...v3.0.1)
11
33
 
data/lib/pdk/cli/build.rb CHANGED
@@ -22,8 +22,6 @@ module PDK
22
22
  log_level: :info
23
23
  )
24
24
 
25
- PDK::CLI::Util.analytics_screen_view('build', opts)
26
-
27
25
  module_metadata = PDK::Module::Metadata.from_file('metadata.json')
28
26
 
29
27
  # TODO: Ensure forge metadata has been set, or call out to interview
@@ -23,8 +23,6 @@ module PDK
23
23
  screen_view_name << args[0] if args.size >= 1
24
24
  screen_view_name << args[1] if args.size >= 2 && args[0] == 'exec'
25
25
 
26
- PDK::CLI::Util.analytics_screen_view(screen_view_name.join('_'))
27
-
28
26
  # Ensure that the correct Ruby is activated before running command.
29
27
  puppet_env = PDK::CLI::Util.puppet_from_opts_or_env({})
30
28
  PDK::Util::RubyVersion.use(puppet_env[:ruby_version])
@@ -34,8 +34,6 @@ module PDK
34
34
 
35
35
  PDK::CLI::Util.validate_puppet_version_opts(processed_options)
36
36
 
37
- PDK::CLI::Util.analytics_screen_view('console', args)
38
-
39
37
  # TODO: figure out if we need to remove default configs set by puppet
40
38
  # so it is scoped for the module only
41
39
  # "--environmentpath"...
@@ -18,7 +18,9 @@ module PDK
18
18
  # Write the context information to the debug log
19
19
  PDK.context.to_debug_log
20
20
 
21
- raise PDK::CLI::ExitWithError, '`pdk convert` can only be run from inside a valid module directory.' unless PDK.context.is_a?(PDK::Context::Module)
21
+ unless PDK.context.is_a?(PDK::Context::Module) || PDK.context.is_a?(PDK::Context::ControlRepo)
22
+ raise PDK::CLI::ExitWithError, '`pdk convert` can only be run from inside a valid module directory.'
23
+ end
22
24
 
23
25
  raise PDK::CLI::ExitWithError, 'You can not specify --noop and --force when converting a module' if opts[:noop] && opts[:force]
24
26
 
@@ -31,8 +33,6 @@ module PDK
31
33
 
32
34
  PDK::CLI::Util.validate_template_opts(opts)
33
35
 
34
- PDK::CLI::Util.analytics_screen_view('convert', opts)
35
-
36
36
  if opts[:'skip-interview'] && opts[:'full-interview']
37
37
  PDK.logger.info 'Ignoring --full-interview and continuing with --skip-interview.'
38
38
  opts[:'full-interview'] = false
data/lib/pdk/cli/env.rb CHANGED
@@ -17,8 +17,6 @@ module PDK
17
17
 
18
18
  PDK::CLI::Util.validate_puppet_version_opts(opts)
19
19
 
20
- PDK::CLI::Util.analytics_screen_view('env')
21
-
22
20
  # Ensure that the correct Ruby is activated before running command.
23
21
  puppet_env = PDK::CLI::Util.puppet_from_opts_or_env(opts)
24
22
  PDK::Util::RubyVersion.use(puppet_env[:ruby_version])
@@ -22,8 +22,6 @@ module PDK
22
22
 
23
23
  raise PDK::CLI::ExitWithError, format("'%{name}' is not a valid class name", name: class_name) unless Util::OptionValidator.valid_class_name?(class_name)
24
24
 
25
- PDK::CLI::Util.analytics_screen_view('new_class', opts)
26
-
27
25
  updates = PDK::Generate::PuppetClass.new(PDK.context, class_name, opts).run
28
26
  PDK::CLI::Util::UpdateManagerPrinter.print_summary(updates, tense: :past)
29
27
  end
@@ -20,8 +20,6 @@ module PDK
20
20
 
21
21
  raise PDK::CLI::ExitWithError, format("'%{name}' is not a valid defined type name", name: defined_type_name) unless Util::OptionValidator.valid_defined_type_name?(defined_type_name)
22
22
 
23
- PDK::CLI::Util.analytics_screen_view('new_defined_type', opts)
24
-
25
23
  require 'pdk/generate/defined_type'
26
24
 
27
25
  updates = PDK::Generate::DefinedType.new(PDK.context, defined_type_name, opts).run
@@ -17,8 +17,6 @@ module PDK
17
17
 
18
18
  raise PDK::CLI::ExitWithError, format("'%{name}' is not a valid fact name", name: fact_name) unless Util::OptionValidator.valid_fact_name?(fact_name)
19
19
 
20
- PDK::CLI::Util.analytics_screen_view('new_fact', opts)
21
-
22
20
  require 'pdk/generate/fact'
23
21
 
24
22
  updates = PDK::Generate::Fact.new(PDK.context, fact_name, opts).run
@@ -18,8 +18,6 @@ module PDK
18
18
 
19
19
  raise PDK::CLI::ExitWithError, format("'%{name}' is not a valid function name", name: function_name) unless Util::OptionValidator.valid_function_name?(function_name)
20
20
 
21
- PDK::CLI::Util.analytics_screen_view('new_function', opts)
22
-
23
21
  require 'pdk/generate/function'
24
22
  updates = PDK::Generate::Function.new(PDK.context, function_name, opts).run
25
23
  PDK::CLI::Util::UpdateManagerPrinter.print_summary(updates, tense: :past)
@@ -22,8 +22,6 @@ module PDK
22
22
 
23
23
  PDK::CLI::Util.validate_template_opts(opts)
24
24
 
25
- PDK::CLI::Util.analytics_screen_view('new_module', opts)
26
-
27
25
  if opts[:'skip-interview'] && opts[:'full-interview']
28
26
  PDK.logger.info 'Ignoring --full-interview and continuing with --skip-interview.'
29
27
  opts[:'full-interview'] = false
@@ -17,8 +17,6 @@ module PDK
17
17
 
18
18
  raise PDK::CLI::ExitWithError, format("'%{name}' is not a valid provider name", name: provider_name) unless Util::OptionValidator.valid_provider_name?(provider_name)
19
19
 
20
- PDK::CLI::Util.analytics_screen_view('new_provider', opts)
21
-
22
20
  require 'pdk/generate/provider'
23
21
 
24
22
  updates = PDK::Generate::Provider.new(PDK.context, provider_name, opts).run
@@ -24,8 +24,6 @@ module PDK
24
24
 
25
25
  raise PDK::CLI::ExitWithError, format("'%{name}' is not a valid task name", name: task_name) unless Util::OptionValidator.valid_task_name?(task_name)
26
26
 
27
- PDK::CLI::Util.analytics_screen_view('new_task', opts)
28
-
29
27
  updates = PDK::Generate::Task.new(PDK.context, task_name, opts).run
30
28
  PDK::CLI::Util::UpdateManagerPrinter.print_summary(updates, tense: :past)
31
29
  end
@@ -39,8 +39,6 @@ module PDK
39
39
  begin
40
40
  generator, obj = PDK::Util::PuppetStrings.find_object(object_name)
41
41
 
42
- PDK::CLI::Util.analytics_screen_view('new_test', opts)
43
-
44
42
  updates = generator.new(PDK.context, obj['name'], opts.merge(spec_only: true)).run
45
43
  PDK::CLI::Util::UpdateManagerPrinter.print_summary(updates, tense: :past)
46
44
  rescue PDK::Util::PuppetStrings::NoObjectError
@@ -28,8 +28,6 @@ module PDK
28
28
 
29
29
  Release.prepare_interview(opts) unless opts[:force]
30
30
 
31
- Release.send_analytics("release #{cmd.name}", opts)
32
-
33
31
  release = PDK::Module::Release.new(nil, opts)
34
32
 
35
33
  Release.module_compatibility_checks!(release, opts)
@@ -37,8 +37,6 @@ module PDK
37
37
 
38
38
  Release.prepare_publish_interview(TTY::Prompt.new(help_color: :cyan), opts) unless opts[:force]
39
39
 
40
- Release.send_analytics("release #{cmd.name}", opts)
41
-
42
40
  release = PDK::Module::Release.new(nil, opts)
43
41
 
44
42
  release.run
@@ -41,8 +41,6 @@ module PDK
41
41
 
42
42
  Release.prepare_interview(opts) unless opts[:force]
43
43
 
44
- Release.send_analytics('release', opts)
45
-
46
44
  release = PDK::Module::Release.new(nil, opts)
47
45
 
48
46
  Release.module_compatibility_checks!(release, opts)
@@ -81,12 +79,6 @@ module PDK
81
79
  end
82
80
  end
83
81
 
84
- # Send_analytics for the given command and Cri options
85
- def self.send_analytics(command, opts)
86
- # Don't pass tokens to analytics
87
- PDK::CLI::Util.analytics_screen_view(command, opts.reject { |k, _| k == :'forge-token' })
88
- end
89
-
90
82
  def self.prepare_interview(opts)
91
83
  questions = []
92
84
 
@@ -34,8 +34,6 @@ module PDK
34
34
 
35
35
  PDK::CLI::Util.module_version_check
36
36
 
37
- PDK::CLI::Util.analytics_screen_view('test_unit', opts)
38
-
39
37
  # Ensure that the bundled gems are up to date and correct Ruby is activated before running or listing tests.
40
38
  puppet_env = PDK::CLI::Util.puppet_from_opts_or_env(opts)
41
39
  PDK::Util::RubyVersion.use(puppet_env[:ruby_version])
@@ -14,7 +14,9 @@ module PDK
14
14
  # Write the context information to the debug log
15
15
  PDK.context.to_debug_log
16
16
 
17
- raise PDK::CLI::ExitWithError, '`pdk update` can only be run from inside a valid module directory.' unless PDK.context.is_a?(PDK::Context::Module)
17
+ unless PDK.context.is_a?(PDK::Context::Module) || PDK.context.is_a?(PDK::Context::ControlRepo)
18
+ raise PDK::CLI::ExitWithError, '`pdk update` can only be run from inside a valid module directory.'
19
+ end
18
20
 
19
21
  raise PDK::CLI::ExitWithError, 'This module does not appear to be PDK compatible. To make the module compatible with PDK, run `pdk convert`.' unless PDK::Util.module_pdk_compatible?
20
22
 
@@ -31,8 +33,6 @@ module PDK
31
33
  end
32
34
  end
33
35
 
34
- PDK::CLI::Util.analytics_screen_view('update', opts)
35
-
36
36
  updater = PDK::Module::Update.new(PDK.context.root_path, opts)
37
37
 
38
38
  if updater.pinned_to_puppetlabs_template_tag?
data/lib/pdk/cli/util.rb CHANGED
@@ -245,44 +245,6 @@ module PDK
245
245
  raise PDK::CLI::ExitWithError, '--template-url may not be used to specify paths containing #\'s.'
246
246
  end
247
247
  module_function :validate_template_opts
248
-
249
- def analytics_screen_view(screen_name, opts = {})
250
- require 'pdk/analytics'
251
-
252
- dimensions = {
253
- ruby_version: RUBY_VERSION
254
- }
255
-
256
- cmd_opts = opts.dup.reject do |_, v|
257
- v.nil? || (v.respond_to?(:empty?) && v.empty?)
258
- end
259
-
260
- if (format_args = cmd_opts.delete(:format))
261
- formats = PDK::CLI::Util::OptionNormalizer.report_formats(format_args)
262
- dimensions[:output_format] = formats.map { |r| r[:method].to_s.delete_prefix('write_') }.sort.uniq.join(',')
263
- else
264
- dimensions[:output_format] = 'default'
265
- end
266
-
267
- safe_opts = [:'puppet-version', :'pe-version']
268
- safe_bools = [true, false]
269
- redacted_opts = cmd_opts.map do |k, v|
270
- value = if safe_bools.include?(v) || safe_opts.include?(k)
271
- v
272
- else
273
- 'redacted'
274
- end
275
- "#{k}=#{value}"
276
- end
277
- dimensions[:cli_options] = redacted_opts.join(',') unless redacted_opts.empty?
278
-
279
- ignored_env_vars = ['PDK_ANALYTICS_CONFIG', 'PDK_DISABLE_ANALYTICS']
280
- env_vars = PDK::Util::Env.select { |k, _| k.start_with?('PDK_') && !ignored_env_vars.include?(k) }.map { |k, v| "#{k}=#{v}" }
281
- dimensions[:env_vars] = env_vars.join(',') unless env_vars.empty?
282
-
283
- PDK.analytics.screen_view(screen_name, **dimensions)
284
- end
285
- module_function :analytics_screen_view
286
248
  end
287
249
  end
288
250
  end
@@ -29,7 +29,6 @@ module PDK
29
29
  require 'pdk/validate'
30
30
 
31
31
  if opts[:list]
32
- PDK::CLI::Util.analytics_screen_view('validate', opts)
33
32
  PDK.logger.info(format('Available validators: %{validator_names}', validator_names: PDK::Validate.validator_names.join(', ')))
34
33
  exit 0
35
34
  end
@@ -75,12 +74,6 @@ module PDK
75
74
  end
76
75
  validators_to_run = PDK::Validate.validator_names if validators_to_run.nil?
77
76
 
78
- if validators_to_run.sort == PDK::Validate.validator_names.sort
79
- PDK::CLI::Util.analytics_screen_view('validate', opts)
80
- else
81
- PDK::CLI::Util.analytics_screen_view(['validate', validators_to_run.sort].flatten.join('_'), opts)
82
- end
83
-
84
77
  # Subsequent arguments are targets.
85
78
  targets.concat(args.to_a[1..]) if args.length > 1
86
79
 
data/lib/pdk/cli.rb CHANGED
@@ -16,7 +16,6 @@ module Cri
16
16
  class CriExitException
17
17
  def initialize(is_error:)
18
18
  @is_error = is_error
19
- PDK.analytics.event('CLI', 'invalid command', label: PDK::CLI.anonymised_args.join(' ')) if error?
20
19
  end
21
20
  end
22
21
  end
@@ -56,7 +55,6 @@ module PDK
56
55
 
57
56
  def self.run(args)
58
57
  @args = args
59
- PDK::Config.analytics_config_interview! unless PDK::Util::Env['PDK_DISABLE_ANALYTICS'] || PDK::Config.analytics_config_exist?
60
58
  @base_cmd.run(args)
61
59
  rescue PDK::CLI::ExitWithError => e
62
60
  PDK.logger.send(e.log_level, e.message)
@@ -24,7 +24,7 @@ module PDK
24
24
  # a child of (defaults to nil).
25
25
  # @option params [self] :persistent_defaults whether default values should be persisted
26
26
  # to disk when evaluated. By default they are not persisted to disk. This is typically
27
- # used for settings which a randomly generated, instead of being deterministic, e.g. analytics user-id
27
+ # used for settings which a randomly generated, instead of being deterministic, e.g. module_defaults author
28
28
  # @param block [Proc] a block that is evaluated within the new instance.
29
29
  def initialize(name = nil, file: nil, parent: nil, persistent_defaults: false, &block)
30
30
  @file = PDK::Util::Filesystem.expand_path(file) unless file.nil?
@@ -162,7 +162,7 @@ module PDK
162
162
  new_hash = {}
163
163
  settings.each_pair { |k, v| new_hash[k] = v.value }
164
164
  @mounts.each_pair { |k, mount_point| new_hash[k] = mount_point.to_h if mount_point.include_in_parent? }
165
- new_hash.delete_if { |_k, v| v.nil? } # rubocop :disable Style/CollectionCompact
165
+ new_hash.delete_if { |_k, v| v.nil? }
166
166
  new_hash
167
167
  end
168
168
 
@@ -238,7 +238,7 @@ module PDK
238
238
  # Returns true when filter is nil.
239
239
  # Returns true if the filter is exactly the same name as the setting.
240
240
  # Returns true if the name is a sub-key of the filter e.g.
241
- # Given a filter of user.module_defaults, `user.module_defaults.author` will return true, but `user.analytics.disabled` will return false.
241
+ # Given a filter of user.module_defaults, `user.module_defaults.author` will return true, but `user.pdk_feature_flags.requested` will return false.
242
242
  #
243
243
  # @param name [String] The setting name to test.
244
244
  # @param filter [String] The filter used to test on the name.
@@ -9,9 +9,9 @@ module PDK
9
9
  #
10
10
  # @example
11
11
  #
12
- # PDK::Config::Namespace.new('analytics') do
13
- # setting :disabled do
14
- # validate PDK::Config::Validator.boolean
12
+ # PDK::Config::Namespace.new('module_defaults') do
13
+ # setting :author do
14
+ # validate PDK::Config::Validator.string
15
15
  # default_to { false }
16
16
  # end
17
17
  # end
data/lib/pdk/config.rb CHANGED
@@ -19,7 +19,6 @@ module PDK
19
19
  # @option options [String] 'system.module_defaults.path' Path to the system module answers PDK configuration file
20
20
  # @option options [String] 'user.path' Path to the user PDK configuration file
21
21
  # @option options [String] 'user.module_defaults.path' Path to the user module answers PDK configuration file
22
- # @option options [String] 'user.analytics.path' Path to the user analytics PDK configuration file
23
22
  # @option options [PDK::Context::AbstractContext] 'context' The context that the configuration should be created in
24
23
  def initialize(options = nil)
25
24
  options = {} if options.nil?
@@ -28,7 +27,6 @@ module PDK
28
27
  'system.module_defaults.path' => PDK::Config.system_answers_path,
29
28
  'user.path' => PDK::Config.user_config_path,
30
29
  'user.module_defaults.path' => PDK::AnswerFile.default_answer_file_path,
31
- 'user.analytics.path' => PDK::Config.analytics_config_path,
32
30
  'context' => PDK.context
33
31
  }.merge(options)
34
32
  end
@@ -51,27 +49,6 @@ module PDK
51
49
  @user_config ||= PDK::Config::JSON.new('user', file: local_options['user.path']) do
52
50
  mount :module_defaults, PDK::Config::JSON.new(file: local_options['user.module_defaults.path'])
53
51
 
54
- # Due to the json-schema gem having issues with Windows based paths, and only supporting Draft 05 (or less) do
55
- # not use JSON validation yet. Once PDK drops support for EOL rubies, we will be able to use the json_schemer gem
56
- # Which has much more modern support
57
- # Reference - https://github.com/puppetlabs/pdk/pull/777
58
- # Reference - https://tickets.puppetlabs.com/browse/PDK-1526
59
- mount :analytics, PDK::Config::YAML.new(file: local_options['user.analytics.path'], persistent_defaults: true) do
60
- setting :disabled do
61
- validate PDK::Config::Validator.boolean
62
- default_to { PDK::Config.bolt_analytics_config.fetch('disabled', true) }
63
- end
64
-
65
- setting 'user-id' do
66
- validate PDK::Config::Validator.uuid
67
- default_to do
68
- require 'securerandom'
69
-
70
- PDK::Config.bolt_analytics_config.fetch('user-id', SecureRandom.uuid)
71
- end
72
- end
73
- end
74
-
75
52
  # Display the feature flags
76
53
  mount :pdk_feature_flags, PDK::Config::Namespace.new('pdk_feature_flags') do
77
54
  setting 'available' do
@@ -191,18 +168,6 @@ module PDK
191
168
  deep_set_object(value, options[:force], send(all_scopes[scope_name]), *names[1..])
192
169
  end
193
170
 
194
- def self.bolt_analytics_config
195
- file = PDK::Util::Filesystem.expand_path('~/.puppetlabs/bolt/analytics.yaml')
196
- PDK::Config::YAML.new(file: file)
197
- rescue PDK::Config::LoadError => e
198
- PDK.logger.debug format('Unable to load %{file}: %{message}', file: file, message: e.message)
199
- PDK::Config::YAML.new
200
- end
201
-
202
- def self.analytics_config_path
203
- PDK::Util::Env['PDK_ANALYTICS_CONFIG'] || File.join(File.dirname(PDK::Util.configdir), 'puppet', 'analytics.yml')
204
- end
205
-
206
171
  def self.user_config_path
207
172
  File.join(PDK::Util.configdir, 'user_config.json')
208
173
  end
@@ -224,51 +189,6 @@ module PDK
224
189
  File.join(json_schemas_path, "#{name}_schema.json")
225
190
  end
226
191
 
227
- def self.analytics_config_exist?
228
- PDK::Util::Filesystem.file?(analytics_config_path)
229
- end
230
-
231
- def self.analytics_config_interview!
232
- require 'pdk/cli/util'
233
-
234
- return unless PDK::CLI::Util.interactive?
235
-
236
- pre_message =
237
- format('PDK collects anonymous usage information to help us understand how ' \
238
- 'it is being used and make decisions on how to improve it. You can ' \
239
- 'find out more about what data we collect and how it is used in the ' \
240
- "PDK documentation at %{url}.\n", url: 'https://puppet.com/docs/pdk/latest/pdk_install.html')
241
- post_message =
242
- format('You can opt in or out of the usage data collection at any time by ' \
243
- 'editing the analytics configuration file at %{path} and changing ' \
244
- "the '%{key}' value.", path: PDK::Config.analytics_config_path, key: 'disabled')
245
-
246
- questions = [
247
- {
248
- name: 'enabled',
249
- question: 'Do you consent to the collection of anonymous PDK usage information?',
250
- type: :yes
251
- }
252
- ]
253
-
254
- require 'pdk/cli/util/interview'
255
-
256
- PDK.logger.info(text: pre_message, wrap: true)
257
- prompt = TTY::Prompt.new(help_color: :cyan)
258
- interview = PDK::CLI::Util::Interview.new(prompt)
259
- interview.add_questions(questions)
260
- answers = interview.run
261
-
262
- if answers.nil?
263
- PDK.logger.info 'No answer given, opting out of analytics collection.'
264
- PDK.config.set(['user', 'analytics', 'disabled'], true)
265
- else
266
- PDK.config.set(['user', 'analytics', 'disabled'], !answers['enabled'])
267
- end
268
-
269
- PDK.logger.info(text: post_message, wrap: true)
270
- end
271
-
272
192
  private
273
193
 
274
194
  # :nocov: This is a private method and is tested elsewhere
@@ -148,7 +148,7 @@ module PDK
148
148
  module_name = new_metadata.nil? ? 'new-module' : new_metadata.data['name']
149
149
  metadata_for_render = new_metadata.nil? ? {} : new_metadata.data
150
150
 
151
- template_dir.render_new_module(module_name, metadata_for_render) do |relative_file_path, file_content, file_status|
151
+ template_dir.render_new_module(module_name, metadata_for_render) do |relative_file_path, file_content, file_status, file_executable|
152
152
  absolute_file_path = File.join(module_dir, relative_file_path)
153
153
  case file_status
154
154
  when :unmanage
@@ -156,12 +156,17 @@ module PDK
156
156
  when :delete
157
157
  update_manager.remove_file(absolute_file_path)
158
158
  when :init
159
- update_manager.add_file(absolute_file_path, file_content) if convert? && !PDK::Util::Filesystem.exist?(absolute_file_path)
159
+ if convert? && !PDK::Util::Filesystem.exist?(absolute_file_path)
160
+ update_manager.add_file(absolute_file_path, file_content)
161
+ update_manager.make_file_executable(absolute_file_path) if file_executable
162
+ end
160
163
  when :manage
161
164
  if PDK::Util::Filesystem.exist?(absolute_file_path)
162
165
  update_manager.modify_file(absolute_file_path, file_content)
166
+ update_manager.make_file_executable(absolute_file_path) if file_executable && !PDK::Util::Filesystem.executable?(absolute_file_path)
163
167
  else
164
168
  update_manager.add_file(absolute_file_path, file_content)
169
+ update_manager.make_file_executable(absolute_file_path) if file_executable
165
170
  end
166
171
  end
167
172
  end
@@ -117,7 +117,7 @@ module PDK
117
117
  def to_json(*_args)
118
118
  require 'json'
119
119
 
120
- JSON.pretty_generate(@data.dup.delete_if { |_key, value| value.nil? }) # rubocop:disable Style/CollectionCompact
120
+ JSON.pretty_generate(@data.dup.delete_if { |_key, value| value.nil? })
121
121
  end
122
122
 
123
123
  def write!(path)
@@ -11,6 +11,7 @@ module PDK
11
11
  @modified_files = Set.new
12
12
  @added_files = Set.new
13
13
  @removed_files = Set.new
14
+ @executable_files = Set.new
14
15
  @diff_cache = {}
15
16
  end
16
17
 
@@ -37,6 +38,13 @@ module PDK
37
38
  @removed_files << path
38
39
  end
39
40
 
41
+ # Store a pending file execute mode change.
42
+ #
43
+ # @param path [String] The path to the file to be made executable.
44
+ def make_file_executable(path)
45
+ @executable_files << path
46
+ end
47
+
40
48
  # Generate a summary of the changes that will be applied to the module.
41
49
  #
42
50
  # @raise (see #calculate_diffs)
@@ -49,7 +57,8 @@ module PDK
49
57
  {
50
58
  added: @added_files,
51
59
  removed: @removed_files.select { |f| PDK::Util::Filesystem.exist?(f) },
52
- modified: @diff_cache.compact
60
+ modified: @diff_cache.compact,
61
+ 'made executable': @executable_files
53
62
  }
54
63
  end
55
64
 
@@ -60,7 +69,8 @@ module PDK
60
69
  def changes?
61
70
  !changes[:added].empty? ||
62
71
  !changes[:removed].empty? ||
63
- changes[:modified].any? { |_, value| !value.nil? }
72
+ changes[:modified].any? { |_, value| !value.nil? } ||
73
+ !changes[:'made executable'].empty?
64
74
  end
65
75
 
66
76
  # Check if the update manager will change the specified file upon sync.
@@ -72,13 +82,15 @@ module PDK
72
82
  def changed?(path)
73
83
  changes[:added].any? { |add| add[:path] == path } ||
74
84
  changes[:removed].include?(path) ||
75
- changes[:modified].key?(path)
85
+ changes[:modified].key?(path) ||
86
+ changes[:'made executable'].include?(path)
76
87
  end
77
88
 
78
89
  def clear!
79
90
  @modified_files.clear
80
91
  @added_files.clear
81
92
  @removed_files.clear
93
+ @executable_files.clear
82
94
  nil
83
95
  end
84
96
 
@@ -100,6 +112,10 @@ module PDK
100
112
  files_to_write.each do |file|
101
113
  write_file(file[:path], file[:content])
102
114
  end
115
+
116
+ @executable_files.each do |file|
117
+ update_execute_bits(file)
118
+ end
103
119
  end
104
120
 
105
121
  # Remove a file from disk.
@@ -215,6 +231,16 @@ module PDK
215
231
 
216
232
  output.join($INPUT_RECORD_SEPARATOR)
217
233
  end
234
+
235
+ # Set the execute bits on a file
236
+ def update_execute_bits(path)
237
+ require 'pdk/util/filesystem'
238
+
239
+ PDK.logger.debug(format("making '%{path}' executable", path: path))
240
+ PDK::Util::Filesystem.make_executable(path)
241
+ rescue Errno::EACCES
242
+ raise PDK::CLI::ExitWithError, format("You do not have permission to make '%{path}' executable", path: path)
243
+ end
218
244
  end
219
245
  end
220
246
  end
@@ -53,7 +53,7 @@ module PDK
53
53
  # @raise [ArgumentError] (see #sanitise_data)
54
54
  def initialize(data)
55
55
  sanitise_data(data).each do |key, value|
56
- instance_variable_set("@#{key}", value)
56
+ instance_variable_set(:"@#{key}", value)
57
57
  end
58
58
  end
59
59
 
@@ -43,7 +43,6 @@ module PDK
43
43
  # @api private
44
44
  def config_for(dest_path, sync_config_path = nil)
45
45
  require 'pdk/util'
46
- require 'pdk/analytics'
47
46
 
48
47
  module_root = PDK::Util.module_root
49
48
  sync_config_path ||= File.join(module_root, '.sync.yml') unless module_root.nil?
@@ -56,22 +55,20 @@ module PDK
56
55
  @config = conf_defaults
57
56
  @config.deep_merge!(@sync_config, knockout_prefix: '---') unless @sync_config.nil?
58
57
  end
59
- file_config = @config.fetch(:global, {})
58
+ file_config = @config.fetch('common', {}).clone
60
59
  file_config['module_metadata'] = @module_metadata
61
60
  file_config.merge!(@config.fetch(dest_path, {})) unless dest_path.nil?
62
61
  file_config.merge!(@config).tap do |c|
63
62
  if uri.default?
64
- file_value = if c['unmanaged']
65
- 'unmanaged'
66
- elsif c['delete']
67
- 'deleted'
68
- elsif @sync_config&.key?(dest_path)
69
- 'customized'
70
- else
71
- 'default'
72
- end
73
-
74
- PDK.analytics.event('TemplateDir', 'file', label: dest_path, value: file_value)
63
+ if c['unmanaged']
64
+ 'unmanaged'
65
+ elsif c['delete']
66
+ 'deleted'
67
+ elsif @sync_config&.key?(dest_path)
68
+ 'customized'
69
+ else
70
+ 'default'
71
+ end
75
72
  end
76
73
  end
77
74
  end
@@ -95,7 +95,9 @@ module PDK
95
95
  end
96
96
  end
97
97
 
98
- yield dest_path, dest_content, dest_status
98
+ dest_executable = config['manage_execute_permissions'] && PDK::Util::Filesystem.executable?(File.join(template_loc, template_file))
99
+
100
+ yield dest_path, dest_content, dest_status, dest_executable
99
101
  end
100
102
  end
101
103
  # :nocov:
data/lib/pdk/template.rb CHANGED
@@ -44,9 +44,6 @@ module PDK
44
44
  template_dir = TemplateDir.instance(uri, fetcher.path, context)
45
45
  template_dir.metadata = fetcher.metadata
46
46
 
47
- template_type = uri.default? ? 'default' : 'custom'
48
- PDK.analytics.event('TemplateDir', 'initialize', label: template_type)
49
-
50
47
  yield template_dir
51
48
  end
52
49
  nil
@@ -27,6 +27,11 @@ module PDK
27
27
  end
28
28
  module_function :read_file
29
29
 
30
+ def make_executable(file)
31
+ FileUtils.chmod('a+x', file)
32
+ end
33
+ module_function :make_executable
34
+
30
35
  # :nocov:
31
36
  # These methods just wrap core Ruby functionality and
32
37
  # can be ignored for code coverage
@@ -133,6 +138,11 @@ module PDK
133
138
  end
134
139
  end
135
140
  module_function :mv
141
+
142
+ def executable?(*args)
143
+ File.executable?(*args)
144
+ end
145
+ module_function :executable?
136
146
  # :nocov:
137
147
  end
138
148
  end
data/lib/pdk/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module PDK
2
- VERSION = '3.0.1'.freeze
3
- TEMPLATE_REF = '3.0.1'.freeze
2
+ VERSION = '3.2.0'.freeze
3
+ TEMPLATE_REF = '3.2.0'.freeze
4
4
  end
data/lib/pdk.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module PDK
2
- autoload :Analytics, 'pdk/analytics'
3
2
  autoload :AnswerFile, 'pdk/answer_file'
4
3
  autoload :Bolt, 'pdk/bolt'
5
4
  autoload :Config, 'pdk/config'
@@ -58,17 +57,4 @@ module PDK
58
57
 
59
58
  requested_feature_flags.include?(flagname)
60
59
  end
61
-
62
- def self.analytics
63
- @analytics ||= PDK::Analytics.build_client(
64
- logger: PDK.logger,
65
- disabled: PDK::Util::Env['PDK_DISABLE_ANALYTICS'] || PDK.config.get_within_scopes('analytics.disabled', ['user', 'system']),
66
- user_id: PDK.config.get_within_scopes('analytics.user-id', ['user', 'system']),
67
- app_id: "UA-139917834-#{PDK::Util.development_mode? ? '2' : '1'}",
68
- client: :google_analytics,
69
- app_name: 'pdk',
70
- app_version: PDK::VERSION,
71
- app_installer: PDK::Util.package_install? ? 'package' : 'gem'
72
- )
73
- end
74
60
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-20 00:00:00.000000000 Z
11
+ date: 2024-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -204,48 +204,6 @@ dependencies:
204
204
  - - "~>"
205
205
  - !ruby/object:Gem::Version
206
206
  version: '0.5'
207
- - !ruby/object:Gem::Dependency
208
- name: concurrent-ruby
209
- requirement: !ruby/object:Gem::Requirement
210
- requirements:
211
- - - '='
212
- - !ruby/object:Gem::Version
213
- version: 1.1.10
214
- type: :runtime
215
- prerelease: false
216
- version_requirements: !ruby/object:Gem::Requirement
217
- requirements:
218
- - - '='
219
- - !ruby/object:Gem::Version
220
- version: 1.1.10
221
- - !ruby/object:Gem::Dependency
222
- name: facter
223
- requirement: !ruby/object:Gem::Requirement
224
- requirements:
225
- - - "~>"
226
- - !ruby/object:Gem::Version
227
- version: '4.0'
228
- type: :runtime
229
- prerelease: false
230
- version_requirements: !ruby/object:Gem::Requirement
231
- requirements:
232
- - - "~>"
233
- - !ruby/object:Gem::Version
234
- version: '4.0'
235
- - !ruby/object:Gem::Dependency
236
- name: httpclient
237
- requirement: !ruby/object:Gem::Requirement
238
- requirements:
239
- - - "~>"
240
- - !ruby/object:Gem::Version
241
- version: 2.8.3
242
- type: :runtime
243
- prerelease: false
244
- version_requirements: !ruby/object:Gem::Requirement
245
- requirements:
246
- - - "~>"
247
- - !ruby/object:Gem::Version
248
- version: 2.8.3
249
207
  - !ruby/object:Gem::Dependency
250
208
  name: deep_merge
251
209
  requirement: !ruby/object:Gem::Requirement
@@ -273,10 +231,6 @@ files:
273
231
  - README.md
274
232
  - exe/pdk
275
233
  - lib/pdk.rb
276
- - lib/pdk/analytics.rb
277
- - lib/pdk/analytics/client/google_analytics.rb
278
- - lib/pdk/analytics/client/noop.rb
279
- - lib/pdk/analytics/util.rb
280
234
  - lib/pdk/answer_file.rb
281
235
  - lib/pdk/bolt.rb
282
236
  - lib/pdk/cli.rb
@@ -321,7 +275,6 @@ files:
321
275
  - lib/pdk/cli/util/update_manager_printer.rb
322
276
  - lib/pdk/cli/validate.rb
323
277
  - lib/pdk/config.rb
324
- - lib/pdk/config/analytics_schema.json
325
278
  - lib/pdk/config/errors.rb
326
279
  - lib/pdk/config/ini_file.rb
327
280
  - lib/pdk/config/ini_file_setting.rb
@@ -1,141 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Analytics
5
- module Client
6
- class GoogleAnalytics
7
- PROTOCOL_VERSION = 1
8
- TRACKING_URL = 'https://google-analytics.com/collect'.freeze
9
- CUSTOM_DIMENSIONS = {
10
- operating_system: :cd1,
11
- output_format: :cd2,
12
- ruby_version: :cd3,
13
- cli_options: :cd4,
14
- env_vars: :cd5
15
- }.freeze
16
-
17
- attr_reader :user_id, :logger, :app_name, :app_id, :app_version, :app_installer
18
-
19
- def initialize(opts)
20
- # lazy-load expensive gem code
21
- require 'concurrent/configuration'
22
- require 'concurrent/future'
23
- require 'httpclient'
24
- require 'locale'
25
- require 'pdk/analytics/util'
26
-
27
- @http = HTTPClient.new
28
- @user_id = opts[:user_id]
29
- @executor = Concurrent.global_io_executor
30
- @os = PDK::Analytics::Util.fetch_os_async
31
- @logger = opts[:logger]
32
- @app_name = opts[:app_name]
33
- @app_id = opts[:app_id]
34
- @app_version = opts[:app_version]
35
- @app_installer = opts[:app_installer]
36
- end
37
-
38
- def screen_view(screen, **kwargs)
39
- custom_dimensions = walk_keys(kwargs) do |k|
40
- CUSTOM_DIMENSIONS[k] || raise(format("Unknown analytics key '%{key}'", key: k))
41
- end
42
-
43
- screen_view_params = {
44
- # Type
45
- t: 'screenview',
46
- # Screen Name
47
- cd: screen
48
- }.merge(custom_dimensions)
49
-
50
- submit(base_params.merge(screen_view_params))
51
- end
52
-
53
- def event(category, action, label: nil, value: nil, **kwargs)
54
- custom_dimensions = walk_keys(kwargs) do |k|
55
- CUSTOM_DIMENSIONS[k] || raise(format("Unknown analytics key '%{key}'", key: k))
56
- end
57
-
58
- event_params = {
59
- # Type
60
- t: 'event',
61
- # Event Category
62
- ec: category,
63
- # Event Action
64
- ea: action
65
- }.merge(custom_dimensions)
66
-
67
- # Event Label
68
- event_params[:el] = label if label
69
- # Event Value
70
- event_params[:ev] = value if value
71
-
72
- submit(base_params.merge(event_params))
73
- end
74
-
75
- def submit(params)
76
- # Handle analytics submission in the background to avoid blocking the
77
- # app or polluting the log with errors
78
- Concurrent::Future.execute(executor: @executor) do
79
- require 'json'
80
-
81
- logger.debug "Submitting analytics: #{JSON.pretty_generate(params)}"
82
- @http.post(TRACKING_URL, params)
83
- logger.debug 'Completed analytics submission'
84
- end
85
- end
86
-
87
- # These parameters have terrible names. See this page for complete documentation:
88
- # https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
89
- def base_params
90
- require 'locale'
91
-
92
- {
93
- v: PROTOCOL_VERSION,
94
- # Client ID
95
- cid: user_id,
96
- # Tracking ID
97
- tid: app_id,
98
- # Application Name
99
- an: app_name,
100
- # Application Version
101
- av: app_version,
102
- # Application Installer ID
103
- aiid: app_installer,
104
- # Anonymize IPs
105
- aip: true,
106
- # User locale
107
- ul: Locale.current.to_rfc,
108
- # Custom Dimension 1 (Operating System)
109
- cd1: @os.value
110
- }
111
- end
112
-
113
- # If the user is running a very fast command, there may not be time for
114
- # analytics submission to complete before the command is finished. In
115
- # that case, we give a little buffer for any stragglers to finish up.
116
- # 250ms strikes a balance between accomodating slower networks while not
117
- # introducing a noticeable "hang".
118
- def finish
119
- @executor.shutdown
120
- @executor.wait_for_termination(0.25)
121
- end
122
-
123
- private
124
-
125
- def walk_keys(data, &block)
126
- case data
127
- when Hash
128
- data.each_with_object({}) do |(k, v), acc|
129
- v = walk_keys(v, &block)
130
- acc[yield(k)] = v
131
- end
132
- when Array
133
- data.map { |v| walk_keys(v, &block) }
134
- else
135
- data
136
- end
137
- end
138
- end
139
- end
140
- end
141
- end
@@ -1,25 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Analytics
5
- module Client
6
- class Noop
7
- attr_reader :logger
8
-
9
- def initialize(opts)
10
- @logger = opts[:logger]
11
- end
12
-
13
- def screen_view(screen, **_kwargs)
14
- logger.debug "Skipping submission of '#{screen}' screenview because analytics is disabled"
15
- end
16
-
17
- def event(category, action, **_kwargs)
18
- logger.debug "Skipping submission of '#{category} #{action}' event because analytics is disabled"
19
- end
20
-
21
- def finish; end
22
- end
23
- end
24
- end
25
- end
@@ -1,18 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Analytics
5
- module Util
6
- def self.fetch_os_async
7
- require 'concurrent/configuration'
8
- require 'concurrent/future'
9
-
10
- Concurrent::Future.execute(executor: :io) do
11
- os = Facter.value('os')
12
-
13
- os.nil? ? 'unknown' : "#{os['name']} #{os.fetch('release', {}).fetch('major', '')}".strip
14
- end
15
- end
16
- end
17
- end
18
- end
data/lib/pdk/analytics.rb DELETED
@@ -1,30 +0,0 @@
1
- require 'pdk'
2
-
3
- autoload :Logger, 'logger'
4
-
5
- module PDK
6
- module Analytics
7
- autoload :Util, 'pdk/analytics/util'
8
-
9
- module Client
10
- autoload :Noop, 'pdk/analytics/client/noop'
11
- autoload :GoogleAnalytics, 'pdk/analytics/client/google_analytics'
12
- end
13
-
14
- def self.build_client(opts = {})
15
- opts[:logger] ||= ::Logger.new($stderr)
16
- opts[:client] ||= :noop
17
-
18
- if opts[:disabled]
19
- opts[:logger].debug 'Analytics opt-out is set, analytics will be disabled'
20
- opts[:client] = :noop
21
- end
22
-
23
- client_const = opts[:client].to_s.split('_').map(&:capitalize).join
24
- PDK::Analytics::Client.const_get(client_const).new(opts)
25
- rescue StandardError => e
26
- opts[:logger].debug "Failed to initialize analytics client, analytics will be disabled: #{e}"
27
- PDK::Analytics::Client::Noop.new(opts)
28
- end
29
- end
30
- end
@@ -1,26 +0,0 @@
1
- {
2
- "definitions": {},
3
- "$schema": "http://json-schema.org/draft-06/schema#",
4
- "$id": "http://puppet.com/schema/does_not_exist.json",
5
- "type": "object",
6
- "title": "The PDK Analytics YAML Schema",
7
- "properties": {
8
- "disabled": {
9
- "$id": "#/properties/disabled",
10
- "type": "boolean",
11
- "title": "Disabled property",
12
- "examples": [
13
- false
14
- ]
15
- },
16
- "user-id": {
17
- "$id": "#/properties/user-id",
18
- "type": "string",
19
- "title": "The User-id for analytics",
20
- "examples": [
21
- "cb9ed65f-37dc-48d8-9863-8bd09cbb61c7"
22
- ],
23
- "pattern": "^[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}$"
24
- }
25
- }
26
- }