openvox-editor-services 3.0.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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +183 -0
  3. data/Gemfile +55 -0
  4. data/LICENSE +201 -0
  5. data/README.md +305 -0
  6. data/Rakefile +260 -0
  7. data/bin/openvox-debugserver +8 -0
  8. data/bin/openvox-languageserver +8 -0
  9. data/bin/openvox-languageserver-sidecar +8 -0
  10. data/bin/puppet-debugserver +8 -0
  11. data/bin/puppet-languageserver +7 -0
  12. data/bin/puppet-languageserver-sidecar +7 -0
  13. data/lib/dsp/dsp.rb +7 -0
  14. data/lib/dsp/dsp_base.rb +62 -0
  15. data/lib/dsp/dsp_protocol.rb +4619 -0
  16. data/lib/lsp/lsp.rb +10 -0
  17. data/lib/lsp/lsp_base.rb +63 -0
  18. data/lib/lsp/lsp_custom.rb +178 -0
  19. data/lib/lsp/lsp_enums.rb +143 -0
  20. data/lib/lsp/lsp_protocol.rb +2785 -0
  21. data/lib/lsp/lsp_protocol_callhierarchy.proposed.rb +239 -0
  22. data/lib/lsp/lsp_protocol_colorprovider.rb +100 -0
  23. data/lib/lsp/lsp_protocol_configuration.rb +82 -0
  24. data/lib/lsp/lsp_protocol_declaration.rb +73 -0
  25. data/lib/lsp/lsp_protocol_foldingrange.rb +129 -0
  26. data/lib/lsp/lsp_protocol_implementation.rb +75 -0
  27. data/lib/lsp/lsp_protocol_progress.rb +200 -0
  28. data/lib/lsp/lsp_protocol_selectionrange.rb +79 -0
  29. data/lib/lsp/lsp_protocol_sematictokens.proposed.rb +340 -0
  30. data/lib/lsp/lsp_protocol_typedefinition.rb +75 -0
  31. data/lib/lsp/lsp_protocol_workspacefolders.rb +174 -0
  32. data/lib/lsp/lsp_types.rb +1534 -0
  33. data/lib/openfact_runtime.rb +26 -0
  34. data/lib/openvox_runtime.rb +61 -0
  35. data/lib/puppet-debugserver/debug_session/break_points.rb +137 -0
  36. data/lib/puppet-debugserver/debug_session/flow_control.rb +161 -0
  37. data/lib/puppet-debugserver/debug_session/hook_handlers.rb +295 -0
  38. data/lib/puppet-debugserver/debug_session/puppet_session_run_mode.rb +66 -0
  39. data/lib/puppet-debugserver/debug_session/puppet_session_state.rb +122 -0
  40. data/lib/puppet-debugserver/hooks.rb +132 -0
  41. data/lib/puppet-debugserver/message_handler.rb +277 -0
  42. data/lib/puppet-debugserver/puppet_debug_session.rb +541 -0
  43. data/lib/puppet-debugserver/puppet_monkey_patches.rb +118 -0
  44. data/lib/puppet-languageserver/client_session_state.rb +119 -0
  45. data/lib/puppet-languageserver/crash_dump.rb +50 -0
  46. data/lib/puppet-languageserver/epp/validation_provider.rb +34 -0
  47. data/lib/puppet-languageserver/facter_helper.rb +25 -0
  48. data/lib/puppet-languageserver/global_queues/sidecar_queue.rb +205 -0
  49. data/lib/puppet-languageserver/global_queues/single_instance_queue.rb +126 -0
  50. data/lib/puppet-languageserver/global_queues/validation_queue.rb +102 -0
  51. data/lib/puppet-languageserver/global_queues.rb +16 -0
  52. data/lib/puppet-languageserver/manifest/completion_provider.rb +331 -0
  53. data/lib/puppet-languageserver/manifest/definition_provider.rb +99 -0
  54. data/lib/puppet-languageserver/manifest/document_symbol_provider.rb +228 -0
  55. data/lib/puppet-languageserver/manifest/folding_provider.rb +226 -0
  56. data/lib/puppet-languageserver/manifest/format_on_type_provider.rb +143 -0
  57. data/lib/puppet-languageserver/manifest/hover_provider.rb +221 -0
  58. data/lib/puppet-languageserver/manifest/signature_provider.rb +169 -0
  59. data/lib/puppet-languageserver/manifest/validation_provider.rb +130 -0
  60. data/lib/puppet-languageserver/message_handler.rb +470 -0
  61. data/lib/puppet-languageserver/providers.rb +18 -0
  62. data/lib/puppet-languageserver/puppet_helper.rb +108 -0
  63. data/lib/puppet-languageserver/puppet_lexer_helper.rb +55 -0
  64. data/lib/puppet-languageserver/puppet_lint.rb +9 -0
  65. data/lib/puppet-languageserver/puppet_monkey_patches.rb +39 -0
  66. data/lib/puppet-languageserver/puppet_parser_helper.rb +212 -0
  67. data/lib/puppet-languageserver/puppetfile/validation_provider.rb +185 -0
  68. data/lib/puppet-languageserver/server_capabilities.rb +48 -0
  69. data/lib/puppet-languageserver/session_state/document_store.rb +272 -0
  70. data/lib/puppet-languageserver/session_state/language_client.rb +239 -0
  71. data/lib/puppet-languageserver/session_state/object_cache.rb +162 -0
  72. data/lib/puppet-languageserver/sidecar_protocol.rb +532 -0
  73. data/lib/puppet-languageserver/uri_helper.rb +46 -0
  74. data/lib/puppet-languageserver-sidecar/cache/base.rb +36 -0
  75. data/lib/puppet-languageserver-sidecar/cache/filesystem.rb +111 -0
  76. data/lib/puppet-languageserver-sidecar/cache/null.rb +27 -0
  77. data/lib/puppet-languageserver-sidecar/facter_helper.rb +41 -0
  78. data/lib/puppet-languageserver-sidecar/puppet_environment_monkey_patches.rb +52 -0
  79. data/lib/puppet-languageserver-sidecar/puppet_helper.rb +281 -0
  80. data/lib/puppet-languageserver-sidecar/puppet_modulepath_monkey_patches.rb +146 -0
  81. data/lib/puppet-languageserver-sidecar/puppet_monkey_patches.rb +9 -0
  82. data/lib/puppet-languageserver-sidecar/puppet_parser_helper.rb +77 -0
  83. data/lib/puppet-languageserver-sidecar/puppet_strings_helper.rb +399 -0
  84. data/lib/puppet-languageserver-sidecar/puppet_strings_monkey_patches.rb +16 -0
  85. data/lib/puppet-languageserver-sidecar/sidecar_protocol_extensions.rb +16 -0
  86. data/lib/puppet-languageserver-sidecar/workspace.rb +89 -0
  87. data/lib/puppet_debugserver.rb +163 -0
  88. data/lib/puppet_editor_services/connection/base.rb +62 -0
  89. data/lib/puppet_editor_services/connection/stdio.rb +25 -0
  90. data/lib/puppet_editor_services/connection/tcp.rb +34 -0
  91. data/lib/puppet_editor_services/handler/base.rb +16 -0
  92. data/lib/puppet_editor_services/handler/debug_adapter.rb +63 -0
  93. data/lib/puppet_editor_services/handler/json_rpc.rb +133 -0
  94. data/lib/puppet_editor_services/logging.rb +45 -0
  95. data/lib/puppet_editor_services/protocol/base.rb +27 -0
  96. data/lib/puppet_editor_services/protocol/debug_adapter.rb +135 -0
  97. data/lib/puppet_editor_services/protocol/debug_adapter_messages.rb +171 -0
  98. data/lib/puppet_editor_services/protocol/json_rpc.rb +241 -0
  99. data/lib/puppet_editor_services/protocol/json_rpc_messages.rb +200 -0
  100. data/lib/puppet_editor_services/server/base.rb +42 -0
  101. data/lib/puppet_editor_services/server/stdio.rb +85 -0
  102. data/lib/puppet_editor_services/server/tcp.rb +349 -0
  103. data/lib/puppet_editor_services/server.rb +15 -0
  104. data/lib/puppet_editor_services/version.rb +36 -0
  105. data/lib/puppet_editor_services.rb +8 -0
  106. data/lib/puppet_languageserver.rb +265 -0
  107. data/lib/puppet_languageserver_sidecar.rb +364 -0
  108. metadata +256 -0
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PuppetEditorServices
4
+ PUPPETEDITORSERVICESVERSION = '3.0.0' unless defined? PUPPETEDITORSERVICESVERSION
5
+
6
+ # @api public
7
+ #
8
+ # @return [String] containing the editor services version, e.g. "0.4.0"
9
+ def self.version
10
+ return @editor_services_version if @editor_services_version
11
+
12
+ version_file = File.join(File.dirname(__FILE__), 'VERSION')
13
+ version = read_version_file(version_file)
14
+
15
+ @editor_services_version = version.nil? ? PUPPETEDITORSERVICESVERSION : version
16
+ end
17
+
18
+ # Sets the editor services version
19
+ # Typically only used in testing
20
+ #
21
+ # @return [void]
22
+ #
23
+ # @api private
24
+ def self.version=(version)
25
+ @editor_services_version = version
26
+ end
27
+
28
+ # @api private
29
+ #
30
+ # @return [String] the version -- for example: "0.4.0" or nil if the VERSION
31
+ # file does not exist.
32
+ def self.read_version_file(path)
33
+ File.read(path).chomp if File.exist?(path)
34
+ end
35
+ private_class_method :read_version_file
36
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ %w[
4
+ logging
5
+ version
6
+ ].each do |lib|
7
+ require "puppet_editor_services/#{lib}"
8
+ end
@@ -0,0 +1,265 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ original_verbose = $VERBOSE
5
+ $VERBOSE = nil
6
+
7
+ require 'puppet_editor_services'
8
+ require 'openvox_runtime'
9
+ require 'openfact_runtime'
10
+ require 'optparse'
11
+ require 'logger'
12
+ ensure
13
+ $VERBOSE = original_verbose
14
+ end
15
+
16
+ module PuppetLanguageServer
17
+ def self.version
18
+ PuppetEditorServices.version
19
+ end
20
+
21
+ # Whether the language server is actually in a state that can be used.
22
+ # Typically this is false when a catastrophic error occurs during startup e.g. Puppet is missing.
23
+ #
24
+ # @return [Bool] Whether the language server is actually in a state that can be used
25
+ def self.active?
26
+ @server_is_active
27
+ end
28
+
29
+ def self.static_data_dir
30
+ @static_data_dir ||= File.expand_path(File.join(__dir__, 'puppet-languageserver', 'static_data'))
31
+ end
32
+
33
+ def self.configure_featureflags(flags)
34
+ @flags = flags
35
+ end
36
+
37
+ def self.featureflag?(flagname)
38
+ return false if @flags.nil? || @flags.empty?
39
+
40
+ @flags.include?(flagname)
41
+ end
42
+
43
+ def self.require_gems(options)
44
+ original_verbose = $VERBOSE
45
+ $VERBOSE = nil
46
+ @server_is_active = false
47
+
48
+ # Use a specific OpenVox Gem version if requested.
49
+ if options[:puppet_version].nil?
50
+ OpenVoxRuntime.activate!
51
+ else
52
+ available_openvox_gems = OpenVoxRuntime.available_versions
53
+ if available_openvox_gems.include?(options[:puppet_version])
54
+ OpenVoxRuntime.activate!(options[:puppet_version])
55
+ else
56
+ log_message(:warn, "Unable to use OpenVox version #{options[:puppet_version]}, as only the following versions are available [#{available_openvox_gems.join(', ')}]")
57
+ OpenVoxRuntime.activate!
58
+ end
59
+ end
60
+
61
+ # These libraries do not require the puppet gem and required for the
62
+ # server to respond to clients.
63
+ %w[
64
+ client_session_state
65
+ crash_dump
66
+ message_handler
67
+ server_capabilities
68
+ ].each do |lib|
69
+ require "puppet-languageserver/#{lib}"
70
+ rescue LoadError
71
+ require File.expand_path(File.join(File.dirname(__FILE__), 'puppet-languageserver', lib))
72
+ end
73
+
74
+ begin
75
+ require 'lsp/lsp'
76
+ OpenFactRuntime.activate!
77
+ rescue LoadError => e
78
+ log_message(:error, "Error while loading a critical gem: #{e} #{e.backtrace}")
79
+ return
80
+ end
81
+
82
+ # These libraries require the puppet and LSP gems.
83
+ %w[
84
+ sidecar_protocol
85
+ global_queues
86
+ puppet_lexer_helper
87
+ puppet_parser_helper
88
+ puppet_helper
89
+ facter_helper
90
+ uri_helper
91
+ puppet_monkey_patches
92
+ providers
93
+ ].each do |lib|
94
+ require "puppet-languageserver/#{lib}"
95
+ rescue LoadError
96
+ require File.expand_path(File.join(File.dirname(__FILE__), 'puppet-languageserver', lib))
97
+ end
98
+
99
+ # Validate the feature flags
100
+ unless options[:flags].nil? || options[:flags].empty?
101
+ flags = options[:flags]
102
+ log_message(:debug, "Detected feature flags [#{flags.join(', ')}]")
103
+
104
+ configure_featureflags(flags)
105
+ end
106
+
107
+ @server_is_active = true
108
+ ensure
109
+ $VERBOSE = original_verbose
110
+ end
111
+
112
+ class CommandLineParser
113
+ def self.parse(options)
114
+ # Set defaults here
115
+ args = {
116
+ connection_timeout: 10,
117
+ debug: nil,
118
+ disable_sidecar_cache: false,
119
+ fast_start_langserver: true,
120
+ flags: [],
121
+ ipaddress: 'localhost',
122
+ port: nil,
123
+ puppet_version: nil,
124
+ puppet_settings: [],
125
+ preload_puppet: true,
126
+ stdio: false,
127
+ stop_on_client_exit: true,
128
+ workspace: nil
129
+ }
130
+
131
+ opt_parser = OptionParser.new do |opts|
132
+ opts.banner = 'Usage: puppet-languageserver.rb [options]'
133
+
134
+ opts.on('-pPORT', '--port=PORT', 'TCP Port to listen on. Default is random port') do |port|
135
+ args[:port] = port.to_i
136
+ end
137
+
138
+ opts.on('-ipADDRESS', '--ip=ADDRESS', "IP Address to listen on (0.0.0.0 for all interfaces). Default is #{args[:ipaddress]}") do |ipaddress|
139
+ args[:ipaddress] = ipaddress
140
+ end
141
+
142
+ opts.on('-c', '--no-stop', 'Do not stop the language server once a client disconnects. Default is to stop') do |_misc|
143
+ args[:stop_on_client_exit] = false
144
+ end
145
+
146
+ opts.on('-tTIMEOUT', '--timeout=TIMEOUT', "Stop the language server if a client does not connection within TIMEOUT seconds. A value of zero will not timeout. Default is #{args[:connection_timeout]} seconds") do |timeout|
147
+ args[:connection_timeout] = timeout.to_i
148
+ end
149
+
150
+ opts.on('-d', '--no-preload', '** DEPRECATED ** Do not preload Puppet information when the language server starts. Default is to preload') do |_misc|
151
+ puts '** WARNING ** Using "--no-preload" may cause Puppet Type loading to be incomplete.'
152
+ args[:preload_puppet] = false
153
+ end
154
+
155
+ opts.on('--debug=DEBUG', "Output debug information. Either specify a filename or 'STDOUT'. Default is no debug output") do |debug|
156
+ args[:debug] = debug
157
+ end
158
+
159
+ opts.on('-s', '--slow-start', '** DEPRECATED ** Delay starting the Language Server until Puppet initialisation has completed. Default is to start fast') do |_misc|
160
+ args[:fast_start_langserver] = false
161
+ end
162
+
163
+ opts.on('--stdio', 'Runs the server in stdio mode, without a TCP listener') do |_misc|
164
+ args[:stdio] = true
165
+ end
166
+
167
+ opts.on('--enable-file-cache', '** DEPRECATED ** Enables the file system cache for Puppet Objects (types, class etc.)') do |_misc|
168
+ end
169
+
170
+ # These options are normally passed through to the Sidecar
171
+ opts.on('--[no-]cache', 'Enable or disable all caching inside the sidecar. By default caching is enabled.') do |cache|
172
+ args[:disable_sidecar_cache] = !cache
173
+ end
174
+
175
+ opts.on('--feature-flags=FLAGS', Array, 'A list of comma delimited feature flags') do |flags|
176
+ args[:flags] = flags
177
+ end
178
+
179
+ opts.on('--puppet-settings=TEXT', Array, 'Comma delimited list of settings to pass into Puppet e.g. --vardir,/opt/test-fixture') do |text|
180
+ args[:puppet_settings] = text
181
+ end
182
+
183
+ opts.on('--openvox-version=TEXT', '--puppet-version=TEXT', String, 'The version of the OpenVox Gem to use (defaults to latest version if not specified or unavailable)') do |text|
184
+ args[:puppet_version] = text
185
+ end
186
+
187
+ opts.on('--local-workspace=PATH', '** DEPRECATED ** The workspace or file path that will be used to provide module-specific functionality. Default is no workspace path.') do |_path|
188
+ end
189
+
190
+ opts.on('-h', '--help', 'Prints this help') do
191
+ puts opts
192
+ exit
193
+ end
194
+
195
+ opts.on('-v', '--version', 'Prints the Langauge Server version') do
196
+ puts PuppetLanguageServer.version
197
+ exit
198
+ end
199
+ end
200
+
201
+ opt_parser.parse!(options.dup)
202
+ args
203
+ end
204
+ end
205
+
206
+ def self.log_message(severity, message)
207
+ PuppetEditorServices.log_message(severity, message)
208
+ end
209
+
210
+ def self.init_puppet(options)
211
+ PuppetEditorServices.init_logging(options)
212
+ log_message(:info, "Language Server is v#{PuppetEditorServices.version}")
213
+ log_message(:debug, 'Loading gems...')
214
+ require_gems(options)
215
+ return unless active?
216
+
217
+ log_message(:info, "Using OpenVox gem v#{OpenVoxRuntime.gem_version} (Puppet API v#{Puppet.version})")
218
+ log_message(:info, "Using OpenFact gem v#{OpenFactRuntime.gem_version} (Facter API v#{Facter.version})")
219
+
220
+ raise("Detected OpenVox #{Puppet.version} however the Language Server requires OpenVox 8.0 and above") if Gem::Version.new(Puppet.version) < Gem::Version.new('8.0.0')
221
+
222
+ log_message(:debug, "Detected additional puppet settings #{options[:puppet_settings]}")
223
+ options[:puppet_settings].nil? ? Puppet.initialize_settings : Puppet.initialize_settings(options[:puppet_settings])
224
+
225
+ log_message(:info, 'Initializing settings...')
226
+
227
+ # Remove all other logging destinations except for ours
228
+ Puppet::Util::Log.destinations.clear
229
+ Puppet::Util::Log.newdestination('null_logger')
230
+
231
+ true
232
+ end
233
+
234
+ def self.rpc_server(options)
235
+ log_message(:info, 'Starting RPC Server...')
236
+ options[:servicename] = 'LANGUAGE SERVER'
237
+
238
+ require 'puppet_editor_services/protocol/json_rpc'
239
+
240
+ server_options = options
241
+ protocol_options = { class: PuppetEditorServices::Protocol::JsonRPC }.merge(options)
242
+ handler_options = { class: PuppetLanguageServer::MessageHandler }.merge(options)
243
+
244
+ unless active?
245
+ handler_options[:class] = PuppetLanguageServer::DisabledMessageHandler
246
+ log_message(:info, 'Configured the Language Server to use the Disabled Message Router')
247
+ end
248
+
249
+ if options[:stdio]
250
+ log_message(:debug, 'Using STDIO Server')
251
+ require 'puppet_editor_services/server/stdio'
252
+ server = ::PuppetEditorServices::Server::Stdio.new(server_options, protocol_options, handler_options)
253
+ trap('INT') { server.stop }
254
+ else
255
+ log_message(:debug, 'Using TCP Server')
256
+ require 'puppet_editor_services/server/tcp'
257
+ # TODO: Add max threads?
258
+ server = ::PuppetEditorServices::Server::Tcp.new(server_options, protocol_options, handler_options)
259
+ trap('INT') { server.stop_services(true) }
260
+ end
261
+ server.start
262
+
263
+ log_message(:info, 'Language Server exited.')
264
+ end
265
+ end
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ original_verbose = $VERBOSE
5
+ $VERBOSE = nil
6
+
7
+ require 'puppet_editor_services'
8
+ require 'openvox_runtime'
9
+ require 'openfact_runtime'
10
+ require 'optparse'
11
+ require 'logger'
12
+ require 'json'
13
+
14
+ %w[
15
+ sidecar_protocol
16
+ ].each do |lib|
17
+ require "puppet-languageserver/#{lib}"
18
+ rescue LoadError
19
+ require File.expand_path(File.join(File.dirname(__FILE__), 'puppet-languageserver', lib))
20
+ end
21
+ ensure
22
+ $VERBOSE = original_verbose
23
+ end
24
+
25
+ module PuppetLanguageServerSidecar
26
+ def self.version
27
+ PuppetEditorServices.version
28
+ end
29
+
30
+ def self.configure_featureflags(flags)
31
+ @flags = flags
32
+ end
33
+
34
+ def self.featureflag?(flagname)
35
+ return false if @flags.nil? || @flags.empty?
36
+
37
+ @flags.include?(flagname)
38
+ end
39
+
40
+ def self.require_gems(options)
41
+ original_verbose = $VERBOSE
42
+ $VERBOSE = nil
43
+
44
+ # Use a specific OpenVox Gem version if requested.
45
+ if options[:puppet_version].nil?
46
+ OpenVoxRuntime.activate!
47
+ else
48
+ available_openvox_gems = OpenVoxRuntime.available_versions
49
+ if available_openvox_gems.include?(options[:puppet_version])
50
+ OpenVoxRuntime.activate!(options[:puppet_version])
51
+ else
52
+ log_message(:warn, "Unable to use OpenVox version #{options[:puppet_version]}, as only the following versions are available [#{available_openvox_gems.join(', ')}]")
53
+ OpenVoxRuntime.activate!
54
+ end
55
+ end
56
+ OpenFactRuntime.activate!
57
+
58
+ # Validate the feature flags
59
+ unless options[:flags].nil? || options[:flags].empty?
60
+ flags = options[:flags]
61
+ log_message(:debug, "Detected feature flags [#{options[:flags].join(', ')}]")
62
+
63
+ configure_featureflags(flags)
64
+ end
65
+
66
+ require_list = %w[
67
+ cache/base
68
+ cache/null
69
+ cache/filesystem
70
+ puppet_parser_helper
71
+ sidecar_protocol_extensions
72
+ workspace
73
+ facter_helper
74
+ puppet_helper
75
+ puppet_monkey_patches
76
+ puppet_strings_helper
77
+ ]
78
+
79
+ require_list.each do |lib|
80
+ require "puppet-languageserver-sidecar/#{lib}"
81
+ rescue LoadError
82
+ require File.expand_path(File.join(File.dirname(__FILE__), 'puppet-languageserver-sidecar', lib))
83
+ end
84
+ ensure
85
+ $VERBOSE = original_verbose
86
+ end
87
+
88
+ ACTION_LIST = %w[
89
+ noop
90
+ default_aggregate
91
+ default_classes
92
+ default_datatypes
93
+ default_functions
94
+ default_types
95
+ node_graph
96
+ resource_list
97
+ workspace_aggregate
98
+ workspace_classes
99
+ workspace_datatypes
100
+ workspace_functions
101
+ workspace_types
102
+ facts
103
+ ].freeze
104
+
105
+ class CommandLineParser
106
+ def self.parse(options)
107
+ # Set defaults here
108
+ args = {
109
+ action: nil,
110
+ action_parameters: PuppetLanguageServer::Sidecar::Protocol::ActionParams.new,
111
+ debug: nil,
112
+ disable_cache: false,
113
+ flags: [],
114
+ output: nil,
115
+ puppet_settings: [],
116
+ puppet_version: nil,
117
+ workspace: nil
118
+ }
119
+
120
+ opt_parser = OptionParser.new do |opts|
121
+ opts.banner = 'Usage: puppet-languageserver-sidecar.rb [options]'
122
+
123
+ opts.on('-a', '--action=NAME', ACTION_LIST, "The action for the sidecar to take. Expected #{ACTION_LIST}") do |name|
124
+ args[:action] = name
125
+ end
126
+
127
+ opts.on('-c', '--action-parameters=JSON', 'JSON Encoded string containing the parameters for the sidecar action') do |json_string|
128
+ ap = PuppetLanguageServer::Sidecar::Protocol::ActionParams.new
129
+ begin
130
+ ap.from_json!(json_string)
131
+ args[:action_parameters] = ap
132
+ rescue StandardError => e
133
+ raise "Unable to parse the action parameters: #{e}"
134
+ end
135
+ end
136
+
137
+ opts.on('-w', '--local-workspace=PATH', 'The workspace or file path that will be used to provide module-specific functionality. Default is no workspace path') do |path|
138
+ args[:workspace] = path
139
+ end
140
+
141
+ opts.on('-o', '--output=PATH', 'The file to save the output from the sidecar. Default is output to STDOUT') do |path|
142
+ args[:output] = path
143
+ end
144
+
145
+ opts.on('-p', '--puppet-settings=TEXT', Array, 'Comma delimited list of settings to pass into Puppet e.g. --vardir,/opt/test-fixture') do |text|
146
+ args[:puppet_settings] = text
147
+ end
148
+
149
+ opts.on('--openvox-version=TEXT', '--puppet-version=TEXT', String, 'The version of the OpenVox Gem to use (defaults to latest version if not specified or unavailable)') do |text|
150
+ args[:puppet_version] = text
151
+ end
152
+
153
+ opts.on('-f', '--feature-flags=FLAGS', Array, 'A list of comma delimited feature flags to pass the the sidecar') do |flags|
154
+ args[:flags] = flags
155
+ end
156
+
157
+ opts.on('-n', '--[no-]cache', 'Enable or disable all caching inside the sidecar. By default caching is enabled.') do |cache|
158
+ args[:disable_cache] = !cache
159
+ end
160
+
161
+ opts.on('--debug=DEBUG', "Output debug information. Either specify a filename or 'STDOUT'. Default is no debug output") do |debug|
162
+ args[:debug] = debug
163
+ end
164
+
165
+ opts.on('-h', '--help', 'Prints this help') do
166
+ puts opts
167
+ exit
168
+ end
169
+
170
+ opts.on('-v', '--version', 'Prints the Langauge Server version') do
171
+ puts PuppetLanguageServerSidecar.version
172
+ exit
173
+ end
174
+ end
175
+
176
+ opt_parser.parse!(options.dup)
177
+
178
+ raise('The action parameter is mandatory') if args[:action].nil?
179
+
180
+ args
181
+ end
182
+ end
183
+
184
+ def self.log_message(severity, message)
185
+ PuppetEditorServices.log_message(severity, message)
186
+ end
187
+
188
+ def self.init_puppet_sidecar(options)
189
+ PuppetEditorServices.init_logging(options)
190
+ log_message(:info, "Language Server Sidecar is v#{PuppetLanguageServerSidecar.version}")
191
+ log_message(:debug, 'Loading gems...')
192
+ require_gems(options)
193
+ log_message(:info, "Using OpenVox gem v#{OpenVoxRuntime.gem_version} (Puppet API v#{Puppet.version})")
194
+ log_message(:info, "Using OpenFact gem v#{OpenFactRuntime.gem_version} (Facter API v#{Facter.version})")
195
+
196
+ raise("Detected OpenVox #{Puppet.version} however the Language Server Sidecar requires OpenVox 8.0 and above") if Gem::Version.new(Puppet.version) < Gem::Version.new('8.0.0')
197
+
198
+ log_message(:debug, "Detected additional puppet settings #{options[:puppet_settings]}")
199
+ options[:puppet_settings].nil? ? Puppet.initialize_settings : Puppet.initialize_settings(options[:puppet_settings])
200
+
201
+ PuppetLanguageServerSidecar::Workspace.detect_workspace(options[:workspace])
202
+ log_message(:debug, 'Detected Module Metadata in the workspace') if PuppetLanguageServerSidecar::Workspace.has_module_metadata?
203
+ log_message(:debug, 'Detected Environment Config in the workspace') if PuppetLanguageServerSidecar::Workspace.has_environmentconf?
204
+
205
+ # Remove all other logging destinations except for ours
206
+ Puppet::Util::Log.destinations.clear
207
+ Puppet::Util::Log.newdestination('null_logger')
208
+
209
+ true
210
+ end
211
+
212
+ def self.inject_workspace_as_module
213
+ return false unless PuppetLanguageServerSidecar::Workspace.has_module_metadata?
214
+
215
+ %w[puppet_modulepath_monkey_patches].each do |lib|
216
+ require "puppet-languageserver-sidecar/#{lib}"
217
+ rescue LoadError
218
+ require File.expand_path(File.join(File.dirname(__FILE__), 'puppet-languageserver-sidecar', lib))
219
+ end
220
+
221
+ log_message(:debug, 'Injected the workspace into the module loader')
222
+ true
223
+ end
224
+
225
+ def self.inject_workspace_as_environment
226
+ return false unless PuppetLanguageServerSidecar::Workspace.has_environmentconf?
227
+
228
+ Puppet.settings[:environment] = PuppetLanguageServerSidecar::PuppetHelper::SIDECAR_PUPPET_ENVIRONMENT
229
+
230
+ %w[puppet_environment_monkey_patches].each do |lib|
231
+ require "puppet-languageserver-sidecar/#{lib}"
232
+ rescue LoadError
233
+ require File.expand_path(File.join(File.dirname(__FILE__), 'puppet-languageserver-sidecar', lib))
234
+ end
235
+
236
+ log_message(:debug, 'Injected the workspace into the environment loader')
237
+ true
238
+ end
239
+
240
+ def self.execute(options)
241
+ unless Gem::Version.new(Puppet.version) >= Gem::Version.new('5.0.0')
242
+ log_message(:error, 'Only Puppet Version 5.0 and above is supported.')
243
+ return []
244
+ end
245
+
246
+ log_message(:debug, "Executing #{options[:action]} action")
247
+ case options[:action].downcase
248
+ when 'noop'
249
+ []
250
+
251
+ when 'default_aggregate'
252
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
253
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache, object_types: PuppetLanguageServerSidecar::PuppetHelper.available_documentation_types)
254
+
255
+ when 'default_classes'
256
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
257
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache, object_types: [:class]).classes
258
+
259
+ when 'default_datatypes'
260
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
261
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache, object_types: [:datatype]).datatypes
262
+
263
+ when 'default_functions'
264
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
265
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache, object_types: [:function]).functions
266
+
267
+ when 'default_types'
268
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
269
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache, object_types: [:type]).types
270
+
271
+ when 'node_graph'
272
+ inject_workspace_as_module || inject_workspace_as_environment
273
+ result = PuppetLanguageServerSidecar::Protocol::PuppetNodeGraph.new
274
+ if options[:action_parameters]['source'].nil?
275
+ log_message(:error, 'Missing source action parameter')
276
+ return result.set_error('Missing source action parameter')
277
+ end
278
+ begin
279
+ manifest = File.open(options[:action_parameters]['source'], 'r:UTF-8') { |f| f.read }
280
+ PuppetLanguageServerSidecar::PuppetParserHelper.compile_node_graph(manifest)
281
+ rescue StandardError => e
282
+ log_message(:error, "Unable to compile the manifest. #{e}")
283
+ result.set_error("Unable to compile the manifest. #{e}")
284
+ end
285
+
286
+ when 'resource_list'
287
+ inject_workspace_as_module || inject_workspace_as_environment
288
+ typename = options[:action_parameters]['typename']
289
+ title = options[:action_parameters]['title']
290
+ if typename.nil?
291
+ log_message(:error, 'Missing typename action paramater')
292
+ return []
293
+ end
294
+ PuppetLanguageServerSidecar::PuppetHelper.get_puppet_resource(typename, title)
295
+
296
+ when 'workspace_aggregate'
297
+ return nil unless inject_workspace_as_module || inject_workspace_as_environment
298
+
299
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
300
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache,
301
+ object_types: PuppetLanguageServerSidecar::PuppetHelper.available_documentation_types,
302
+ root_path: PuppetLanguageServerSidecar::Workspace.root_path)
303
+
304
+ when 'workspace_classes'
305
+ return nil unless inject_workspace_as_module || inject_workspace_as_environment
306
+
307
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
308
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache,
309
+ object_types: [:class],
310
+ root_path: PuppetLanguageServerSidecar::Workspace.root_path).classes
311
+
312
+ when 'workspace_datatypes'
313
+ return nil unless inject_workspace_as_module || inject_workspace_as_environment
314
+
315
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
316
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache,
317
+ object_types: [:datatype],
318
+ root_path: PuppetLanguageServerSidecar::Workspace.root_path).datatypes
319
+
320
+ when 'workspace_functions'
321
+ return nil unless inject_workspace_as_module || inject_workspace_as_environment
322
+
323
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
324
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache,
325
+ object_types: [:function],
326
+ root_path: PuppetLanguageServerSidecar::Workspace.root_path).functions
327
+
328
+ when 'workspace_types'
329
+ return nil unless inject_workspace_as_module || inject_workspace_as_environment
330
+
331
+ cache = options[:disable_cache] ? PuppetLanguageServerSidecar::Cache::Null.new : PuppetLanguageServerSidecar::Cache::FileSystem.new
332
+ PuppetLanguageServerSidecar::PuppetHelper.retrieve_via_puppet_strings(cache,
333
+ object_types: [:type],
334
+ root_path: PuppetLanguageServerSidecar::Workspace.root_path).types
335
+
336
+ when 'facts'
337
+ # Can't cache for facts
338
+ cache = PuppetLanguageServerSidecar::Cache::Null.new
339
+ # Inject the workspace etc. if present
340
+ injected = inject_workspace_as_module
341
+ inject_workspace_as_environment unless injected
342
+ PuppetLanguageServerSidecar::FacterHelper.retrieve_facts(cache)
343
+
344
+ else
345
+ log_message(:error, "Unknown action #{options[:action]}. Expected one of #{ACTION_LIST}")
346
+ end
347
+ end
348
+
349
+ def self.output(result, options)
350
+ if options[:output].nil? || options[:output].empty?
351
+ $stdout.binmode
352
+ $stdout.write(result.to_json)
353
+ else
354
+ File.open(options[:output], 'wb:UTF-8') do |f|
355
+ f.write result.to_json
356
+ end
357
+ end
358
+ end
359
+
360
+ def self.execute_and_output(options)
361
+ output(execute(options), options)
362
+ nil
363
+ end
364
+ end