pdk 1.14.1 → 1.18.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +155 -2
  3. data/lib/pdk.rb +28 -19
  4. data/lib/pdk/answer_file.rb +2 -95
  5. data/lib/pdk/bolt.rb +19 -0
  6. data/lib/pdk/cli.rb +4 -5
  7. data/lib/pdk/cli/bundle.rb +5 -1
  8. data/lib/pdk/cli/config.rb +3 -1
  9. data/lib/pdk/cli/config/get.rb +3 -1
  10. data/lib/pdk/cli/console.rb +1 -1
  11. data/lib/pdk/cli/convert.rb +16 -10
  12. data/lib/pdk/cli/exec.rb +2 -1
  13. data/lib/pdk/cli/exec/command.rb +45 -4
  14. data/lib/pdk/cli/exec_group.rb +78 -43
  15. data/lib/pdk/cli/get.rb +20 -0
  16. data/lib/pdk/cli/get/config.rb +24 -0
  17. data/lib/pdk/cli/module/build.rb +1 -1
  18. data/lib/pdk/cli/module/generate.rb +1 -1
  19. data/lib/pdk/cli/new/class.rb +2 -2
  20. data/lib/pdk/cli/new/defined_type.rb +2 -2
  21. data/lib/pdk/cli/new/provider.rb +2 -2
  22. data/lib/pdk/cli/new/task.rb +2 -2
  23. data/lib/pdk/cli/new/test.rb +2 -2
  24. data/lib/pdk/cli/new/transport.rb +2 -2
  25. data/lib/pdk/cli/release.rb +192 -0
  26. data/lib/pdk/cli/release/prep.rb +39 -0
  27. data/lib/pdk/cli/release/publish.rb +40 -0
  28. data/lib/pdk/cli/remove.rb +20 -0
  29. data/lib/pdk/cli/remove/config.rb +80 -0
  30. data/lib/pdk/cli/set.rb +20 -0
  31. data/lib/pdk/cli/set/config.rb +119 -0
  32. data/lib/pdk/cli/update.rb +18 -8
  33. data/lib/pdk/cli/util.rb +7 -3
  34. data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
  35. data/lib/pdk/cli/validate.rb +26 -44
  36. data/lib/pdk/config.rb +265 -8
  37. data/lib/pdk/config/ini_file.rb +183 -0
  38. data/lib/pdk/config/ini_file_setting.rb +39 -0
  39. data/lib/pdk/config/namespace.rb +26 -6
  40. data/lib/pdk/config/setting.rb +3 -2
  41. data/lib/pdk/context.rb +99 -0
  42. data/lib/pdk/context/control_repo.rb +60 -0
  43. data/lib/pdk/context/module.rb +28 -0
  44. data/lib/pdk/context/none.rb +22 -0
  45. data/lib/pdk/control_repo.rb +90 -0
  46. data/lib/pdk/generate.rb +1 -0
  47. data/lib/pdk/generate/defined_type.rb +25 -32
  48. data/lib/pdk/generate/module.rb +42 -35
  49. data/lib/pdk/generate/provider.rb +16 -65
  50. data/lib/pdk/generate/puppet_class.rb +25 -31
  51. data/lib/pdk/generate/puppet_object.rb +84 -189
  52. data/lib/pdk/generate/resource_api_object.rb +55 -0
  53. data/lib/pdk/generate/task.rb +28 -46
  54. data/lib/pdk/generate/transport.rb +21 -75
  55. data/lib/pdk/module.rb +1 -1
  56. data/lib/pdk/module/build.rb +38 -25
  57. data/lib/pdk/module/convert.rb +61 -42
  58. data/lib/pdk/module/metadata.rb +1 -3
  59. data/lib/pdk/module/release.rb +254 -0
  60. data/lib/pdk/module/update.rb +24 -16
  61. data/lib/pdk/module/update_manager.rb +8 -1
  62. data/lib/pdk/report.rb +18 -12
  63. data/lib/pdk/report/event.rb +6 -3
  64. data/lib/pdk/template.rb +59 -0
  65. data/lib/pdk/template/fetcher.rb +98 -0
  66. data/lib/pdk/template/fetcher/git.rb +85 -0
  67. data/lib/pdk/template/fetcher/local.rb +28 -0
  68. data/lib/pdk/template/renderer.rb +96 -0
  69. data/lib/pdk/template/renderer/v1.rb +25 -0
  70. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +116 -0
  71. data/lib/pdk/template/renderer/v1/renderer.rb +132 -0
  72. data/lib/pdk/template/renderer/v1/template_file.rb +102 -0
  73. data/lib/pdk/template/template_dir.rb +67 -0
  74. data/lib/pdk/tests/unit.rb +5 -0
  75. data/lib/pdk/util.rb +55 -45
  76. data/lib/pdk/util/bundler.rb +9 -9
  77. data/lib/pdk/util/changelog_generator.rb +120 -0
  78. data/lib/pdk/util/env.rb +28 -11
  79. data/lib/pdk/util/filesystem.rb +62 -2
  80. data/lib/pdk/util/git.rb +60 -8
  81. data/lib/pdk/util/json_finder.rb +84 -0
  82. data/lib/pdk/util/puppet_strings.rb +3 -3
  83. data/lib/pdk/util/puppet_version.rb +4 -5
  84. data/lib/pdk/util/ruby_version.rb +9 -6
  85. data/lib/pdk/util/template_uri.rb +60 -48
  86. data/lib/pdk/util/version.rb +4 -4
  87. data/lib/pdk/validate.rb +79 -25
  88. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
  89. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
  90. data/lib/pdk/validate/external_command_validator.rb +208 -0
  91. data/lib/pdk/validate/internal_ruby_validator.rb +100 -0
  92. data/lib/pdk/validate/invokable_validator.rb +215 -0
  93. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +86 -0
  94. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +78 -0
  95. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
  96. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +133 -0
  97. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
  98. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +137 -0
  99. data/lib/pdk/validate/puppet/puppet_validator_group.rb +21 -0
  100. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +80 -0
  101. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
  102. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +88 -0
  103. data/lib/pdk/validate/tasks/tasks_name_validator.rb +50 -0
  104. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
  105. data/lib/pdk/validate/validator.rb +118 -0
  106. data/lib/pdk/validate/validator_group.rb +104 -0
  107. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +95 -0
  108. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
  109. data/lib/pdk/version.rb +1 -1
  110. data/locales/pdk.pot +755 -319
  111. metadata +66 -24
  112. data/lib/pdk/module/templatedir.rb +0 -391
  113. data/lib/pdk/template_file.rb +0 -96
  114. data/lib/pdk/validate/base_validator.rb +0 -215
  115. data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -82
  116. data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -111
  117. data/lib/pdk/validate/metadata_validator.rb +0 -26
  118. data/lib/pdk/validate/puppet/puppet_epp.rb +0 -137
  119. data/lib/pdk/validate/puppet/puppet_lint.rb +0 -64
  120. data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -137
  121. data/lib/pdk/validate/puppet_validator.rb +0 -26
  122. data/lib/pdk/validate/ruby/rubocop.rb +0 -72
  123. data/lib/pdk/validate/ruby_validator.rb +0 -26
  124. data/lib/pdk/validate/tasks/metadata_lint.rb +0 -130
  125. data/lib/pdk/validate/tasks/name.rb +0 -90
  126. data/lib/pdk/validate/tasks_validator.rb +0 -29
  127. data/lib/pdk/validate/yaml/syntax.rb +0 -125
  128. data/lib/pdk/validate/yaml_validator.rb +0 -28
@@ -1,96 +0,0 @@
1
- require 'ostruct'
2
- require 'pdk'
3
-
4
- module PDK
5
- class TemplateFile < OpenStruct
6
- # Initialises the TemplateFile object with the path to the template file
7
- # and the data to be used when rendering the template.
8
- #
9
- # @param template_file [String] The path on disk to the template file.
10
- # @param data [Hash{Symbol => Object}] The data that should be provided to
11
- # the template when rendering.
12
- # @option data [Object] :configs The value of this key will be provided to
13
- # the template as an instance variable `@configs` in order to maintain
14
- # compatibility with modulesync.
15
- #
16
- # @api public
17
- def initialize(template_file, data = {})
18
- @template_file = template_file
19
-
20
- if data.key?(:configs)
21
- @configs = data[:configs]
22
- end
23
-
24
- super(data)
25
- end
26
-
27
- # Renders the template by calling the appropriate engine based on the file
28
- # extension.
29
- #
30
- # If the template has an `.erb` extension, the content of the template
31
- # file will be treated as an ERB template. All other extensions are treated
32
- # as plain text.
33
- #
34
- # @return [String] The rendered template
35
- #
36
- # @raise (see #template_content)
37
- #
38
- # @api public
39
- def render
40
- case File.extname(@template_file)
41
- when '.erb'
42
- render_erb
43
- else
44
- render_plain
45
- end
46
- end
47
-
48
- def config_for(path)
49
- return unless respond_to?(:template_dir)
50
-
51
- template_dir.config_for(path)
52
- end
53
-
54
- private
55
-
56
- # Reads the content of the template file into memory.
57
- #
58
- # @return [String] The content of the template file.
59
- #
60
- # @raise [ArgumentError] If the template file does not exist or can not be
61
- # read.
62
- #
63
- # @api private
64
- def template_content
65
- if File.file?(@template_file) && File.readable?(@template_file)
66
- return File.read(@template_file)
67
- end
68
-
69
- raise ArgumentError, _("'%{template}' is not a readable file") % { template: @template_file }
70
- end
71
-
72
- # Renders the content of the template file as an ERB template.
73
- #
74
- # @return [String] The rendered template.
75
- #
76
- # @raise (see #template_content)
77
- #
78
- # @api private
79
- def render_erb
80
- renderer = ERB.new(template_content, nil, '-')
81
- renderer.filename = @template_file
82
- renderer.result(binding)
83
- end
84
-
85
- # Renders the content of the template file as plain text.
86
- #
87
- # @return [String] The rendered template.
88
- #
89
- # @raise (see #template_content)
90
- #
91
- # @api private
92
- def render_plain
93
- template_content
94
- end
95
- end
96
- end
@@ -1,215 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Validate
5
- class BaseValidator
6
- # Controls how many times the validator is invoked.
7
- #
8
- # :once - The validator will be invoked once and passed all the
9
- # targets.
10
- # :per_target - The validator will be invoked for each target
11
- # separately.
12
- INVOKE_STYLE = :once
13
-
14
- # Controls how the validator behaves if not passed any targets.
15
- #
16
- # true - PDK will not pass the globbed targets to the validator command
17
- # and it will instead rely on the underlying tool to find its
18
- # own default targets.
19
- # false - PDK will pass the globbed targets to the validator command.
20
- ALLOW_EMPTY_TARGETS = false
21
-
22
- IGNORE_DOTFILES = true
23
-
24
- def self.cmd_path
25
- File.join(PDK::Util.module_root, 'bin', cmd)
26
- end
27
-
28
- # Parses the target strings provided from the CLI
29
- #
30
- # @param options [Hash] A Hash containing the input options from the CLI.
31
- #
32
- # @return targets [Array] An Array of Strings containing target file paths
33
- # for the validator to validate.
34
- # @return skipped [Array] An Array of Strings containing targets
35
- # that are skipped due to target not containing
36
- # any files that can be validated by the validator.
37
- # @return invalid [Array] An Array of Strings containing targets that do
38
- # not exist, and will not be run by validator.
39
- def self.parse_targets(options)
40
- # If no targets are specified, then we will run validations from the
41
- # base module directory.
42
-
43
- targets = options.fetch(:targets, []).empty? ? [PDK::Util.module_root] : options[:targets]
44
-
45
- targets.map! { |r| r.gsub(File::ALT_SEPARATOR, File::SEPARATOR) } if File::ALT_SEPARATOR
46
- skipped = []
47
- invalid = []
48
- matched = targets.map { |target|
49
- if respond_to?(:pattern)
50
- if PDK::Util::Filesystem.directory?(target)
51
- target_root = PDK::Util.module_root
52
- pattern_glob = Array(pattern).map { |p| PDK::Util::Filesystem.glob(File.join(target_root, p), File::FNM_DOTMATCH) }
53
- target_list = pattern_glob.flatten
54
- .select { |glob| PDK::Util::Filesystem.fnmatch(File.join(PDK::Util::Filesystem.expand_path(PDK::Util.canonical_path(target)), '*'), glob, File::FNM_DOTMATCH) }
55
- .map { |glob| Pathname.new(glob).relative_path_from(Pathname.new(PDK::Util.module_root)).to_s }
56
-
57
- ignore_list = ignore_pathspec
58
- target_list = target_list.reject { |file| ignore_list.match(file) }
59
-
60
- skipped << target if target_list.flatten.empty?
61
- target_list
62
- elsif PDK::Util::Filesystem.file?(target)
63
- if Array(pattern).include? target
64
- target
65
- elsif Array(pattern).any? { |p| PDK::Util::Filesystem.fnmatch(PDK::Util::Filesystem.expand_path(p), PDK::Util::Filesystem.expand_path(target), File::FNM_DOTMATCH) }
66
- target
67
- else
68
- skipped << target
69
- next
70
- end
71
- else
72
- invalid << target
73
- next
74
- end
75
- else
76
- target
77
- end
78
- }.compact.flatten
79
- [matched, skipped, invalid]
80
- end
81
-
82
- def self.ignore_pathspec
83
- require 'pdk/module'
84
-
85
- ignore_pathspec = PDK::Module.default_ignored_pathspec(ignore_dotfiles?)
86
-
87
- if respond_to?(:pattern_ignore)
88
- Array(pattern_ignore).each do |pattern|
89
- ignore_pathspec.add(pattern)
90
- end
91
- end
92
-
93
- ignore_pathspec
94
- end
95
-
96
- def self.ignore_dotfiles?
97
- self::IGNORE_DOTFILES
98
- end
99
-
100
- def self.parse_options(_options, targets)
101
- targets
102
- end
103
-
104
- def self.spinner_text(_targets = nil)
105
- _('Invoking %{cmd}') % { cmd: cmd }
106
- end
107
-
108
- def self.process_skipped(report, skipped = [])
109
- skipped.each do |skipped_target|
110
- PDK.logger.debug(_('%{validator}: Skipped \'%{target}\'. Target does not contain any files to validate (%{pattern}).') % { validator: name, target: skipped_target, pattern: pattern })
111
- report.add_event(
112
- file: skipped_target,
113
- source: name,
114
- message: _('Target does not contain any files to validate (%{pattern}).') % { pattern: pattern },
115
- severity: :info,
116
- state: :skipped,
117
- )
118
- end
119
- end
120
-
121
- def self.process_invalid(report, invalid = [])
122
- invalid.each do |invalid_target|
123
- PDK.logger.debug(_('%{validator}: Skipped \'%{target}\'. Target file not found.') % { validator: name, target: invalid_target })
124
- report.add_event(
125
- file: invalid_target,
126
- source: name,
127
- message: _('File does not exist.'),
128
- severity: :error,
129
- state: :error,
130
- )
131
- end
132
- end
133
-
134
- def self.allow_empty_targets?
135
- self::ALLOW_EMPTY_TARGETS == true
136
- end
137
-
138
- def self.invoke(report, options = {})
139
- require 'pdk/cli/exec/command'
140
-
141
- targets, skipped, invalid = parse_targets(options)
142
-
143
- process_skipped(report, skipped)
144
- process_invalid(report, invalid)
145
-
146
- return 0 if targets.empty?
147
-
148
- PDK::Util::Bundler.ensure_binstubs!(cmd)
149
-
150
- # If invoking :per_target, split the targets array into an array of
151
- # single element arrays (one per target). If invoking :once, wrap the
152
- # targets array in another array. This is so we can loop through the
153
- # invokes with the same logic, regardless of which invoke style is
154
- # needed.
155
- #
156
- if self::INVOKE_STYLE == :per_target
157
- targets = targets.combination(1).to_a
158
- else
159
- require 'pdk/cli/exec_group'
160
- targets = targets.each_slice(1000).to_a
161
- options[:split_exec] = PDK::CLI::ExecGroup.new(spinner_text(targets), parallel: false)
162
- end
163
-
164
- if options.fetch(:targets, []).empty? && allow_empty_targets?
165
- targets = [[]]
166
- end
167
-
168
- exit_codes = []
169
-
170
- targets.each do |invokation_targets|
171
- cmd_argv = parse_options(options, invokation_targets).unshift(cmd_path).compact
172
- cmd_argv.unshift(File.join(PDK::Util::RubyVersion.bin_path, 'ruby.exe'), '-W0') if Gem.win_platform?
173
-
174
- command = PDK::CLI::Exec::Command.new(*cmd_argv).tap do |c|
175
- c.context = :module
176
- c.environment = { 'PUPPET_GEM_VERSION' => options[:puppet] } if options[:puppet]
177
- unless options[:split_exec]
178
- exec_group = options[:exec_group]
179
- if exec_group
180
- sub_spinner = exec_group.add_spinner(spinner_text(invokation_targets))
181
- c.register_spinner(sub_spinner)
182
- else
183
- c.add_spinner(spinner_text(invokation_targets))
184
- end
185
- end
186
- end
187
-
188
- if options[:split_exec]
189
- options[:split_exec].register do
190
- result = command.execute!
191
-
192
- begin
193
- parse_output(report, result, invokation_targets.compact)
194
- rescue PDK::Validate::ParseOutputError => e
195
- $stderr.puts e.message
196
- end
197
- result[:exit_code]
198
- end
199
- else
200
- result = command.execute!
201
- exit_codes << result[:exit_code]
202
-
203
- begin
204
- parse_output(report, result, invokation_targets.compact)
205
- rescue PDK::Validate::ParseOutputError => e
206
- $stderr.puts e.message
207
- end
208
- end
209
- end
210
-
211
- options.key?(:split_exec) ? options[:split_exec].exit_code : exit_codes.max
212
- end
213
- end
214
- end
215
- end
@@ -1,82 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Validate
5
- class MetadataJSONLint < BaseValidator
6
- # Validate each metadata file separately, as metadata-json-lint does not
7
- # support multiple targets.
8
- INVOKE_STYLE = :per_target
9
-
10
- def self.name
11
- 'metadata-json-lint'
12
- end
13
-
14
- def self.cmd
15
- 'metadata-json-lint'
16
- end
17
-
18
- def self.spinner_text(targets = [])
19
- _('Checking module metadata style (%{targets}).') % {
20
- targets: PDK::Util.targets_relative_to_pwd(targets).join(' '),
21
- }
22
- end
23
-
24
- def self.pattern
25
- 'metadata.json'
26
- end
27
-
28
- def self.parse_options(_options, targets)
29
- cmd_options = ['--format', 'json']
30
- cmd_options << '--strict-dependencies'
31
-
32
- cmd_options.concat(targets)
33
- end
34
-
35
- def self.parse_output(report, result, targets)
36
- raise ArgumentError, _('More than 1 target provided to PDK::Validate::MetadataJSONLint.') if targets.count > 1
37
-
38
- if result[:stdout].strip.empty?
39
- # metadata-json-lint will print nothing if there are no problems with
40
- # the file being linted. This should be handled separately to
41
- # metadata-json-lint generating output that can not be parsed as JSON
42
- # (unhandled exception in metadata-json-lint).
43
- json_data = {}
44
- else
45
- begin
46
- json_data = JSON.parse(result[:stdout])
47
- rescue JSON::ParserError
48
- raise PDK::Validate::ParseOutputError, result[:stdout]
49
- end
50
- end
51
-
52
- if json_data.empty?
53
- report.add_event(
54
- file: targets.first,
55
- source: name,
56
- state: :passed,
57
- severity: :ok,
58
- )
59
- else
60
- json_data.delete('result')
61
- json_data.keys.each do |type|
62
- json_data[type].each do |offense|
63
- # metadata-json-lint groups the offenses by type, so the type ends
64
- # up being `warnings` or `errors`. We want to convert that to the
65
- # singular noun for the event.
66
- event_type = type[%r{\A(.+?)s?\Z}, 1]
67
-
68
- report.add_event(
69
- file: targets.first,
70
- source: name,
71
- message: offense['msg'],
72
- test: offense['check'],
73
- severity: event_type,
74
- state: :failure,
75
- )
76
- end
77
- end
78
- end
79
- end
80
- end
81
- end
82
- end
@@ -1,111 +0,0 @@
1
- require 'pdk'
2
-
3
- module PDK
4
- module Validate
5
- class MetadataSyntax < BaseValidator
6
- def self.name
7
- 'metadata-syntax'
8
- end
9
-
10
- def self.pattern
11
- ['metadata.json', 'tasks/*.json']
12
- end
13
-
14
- def self.spinner_text(_targets = [])
15
- _('Checking metadata syntax (%{targets}).') % {
16
- targets: pattern.join(' '),
17
- }
18
- end
19
-
20
- def self.create_spinner(targets = [], options = {})
21
- require 'pdk/cli/util'
22
-
23
- return unless PDK::CLI::Util.interactive?
24
-
25
- options = options.merge(PDK::CLI::Util.spinner_opts_for_platform)
26
-
27
- exec_group = options[:exec_group]
28
- @spinner = if exec_group
29
- exec_group.add_spinner(spinner_text(targets), options)
30
- else
31
- require 'pdk/cli/util/spinner'
32
-
33
- TTY::Spinner.new("[:spinner] #{spinner_text(targets)}", options)
34
- end
35
- @spinner.auto_spin
36
- end
37
-
38
- def self.stop_spinner(exit_code)
39
- if exit_code.zero? && @spinner
40
- @spinner.success
41
- elsif @spinner
42
- @spinner.error
43
- end
44
- end
45
-
46
- def self.invoke(report, options = {})
47
- targets, skipped, invalid = parse_targets(options)
48
-
49
- process_skipped(report, skipped)
50
- process_invalid(report, invalid)
51
-
52
- return 0 if targets.empty?
53
-
54
- return_val = 0
55
- create_spinner(targets, options)
56
-
57
- # The pure ruby JSON parser gives much nicer parse error messages than
58
- # the C extension at the cost of slightly slower parsing. We require it
59
- # here and restore the C extension at the end of the method (if it was
60
- # being used).
61
- require 'json/pure'
62
- JSON.parser = JSON::Pure::Parser
63
-
64
- targets.each do |target|
65
- unless File.readable?(target)
66
- report.add_event(
67
- file: target,
68
- source: name,
69
- state: :failure,
70
- severity: 'error',
71
- message: _('Could not be read.'),
72
- )
73
- return_val = 1
74
- next
75
- end
76
-
77
- begin
78
- JSON.parse(File.read(target))
79
-
80
- report.add_event(
81
- file: target,
82
- source: name,
83
- state: :passed,
84
- severity: 'ok',
85
- )
86
- rescue JSON::ParserError => e
87
- # Because the message contains a raw segment of the file, we use
88
- # String#dump here to unescape any escape characters like newlines.
89
- # We then strip out the surrounding quotes and the exclaimation
90
- # point that json_pure likes to put in exception messages.
91
- sane_message = e.message.dump[%r{\A"(.+?)!?"\Z}, 1]
92
-
93
- report.add_event(
94
- file: target,
95
- source: name,
96
- state: :failure,
97
- severity: 'error',
98
- message: sane_message,
99
- )
100
- return_val = 1
101
- end
102
- end
103
-
104
- stop_spinner(return_val)
105
- return_val
106
- ensure
107
- JSON.parser = JSON::Ext::Parser if defined?(JSON::Ext::Parser)
108
- end
109
- end
110
- end
111
- end