Skip to content

Commit 82f768b

Browse files
committed
(GH-213) Gather facts using the Sidecar
Previously the facts where evaluated only within the Editor Service process however this meant the workspace couldn't be injected. This commit adds a new action to the Sidecar process to evaluate the facts. The Sidecar has the required monkey patches to inject the workspace into the fact search directories. This commit also adds tests and fixtures to ensure that custom and external facts can be resolved.
1 parent 4d36a94 commit 82f768b

File tree

13 files changed

+219
-1
lines changed

13 files changed

+219
-1
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
module PuppetLanguageServerSidecar
4+
module FacterHelper
5+
def self.current_environment
6+
begin
7+
env = Puppet.lookup(:environments).get!(Puppet.settings[:environment])
8+
return env unless env.nil?
9+
rescue Puppet::Environments::EnvironmentNotFound
10+
PuppetLanguageServerSidecar.log_message(:warning, "[FacterHelper::current_environment] Unable to load environment #{Puppet.settings[:environment]}")
11+
rescue StandardError => e
12+
PuppetLanguageServerSidecar.log_message(:warning, "[FacterHelper::current_environment] Error loading environment #{Puppet.settings[:environment]}: #{e}")
13+
end
14+
Puppet.lookup(:current_environment)
15+
end
16+
17+
def self.retrieve_facts(_cache, _options = {})
18+
require 'puppet/indirector/facts/facter'
19+
20+
PuppetLanguageServerSidecar.log_message(:debug, '[FacterHelper::retrieve_facts] Starting')
21+
facts = PuppetLanguageServer::Sidecar::Protocol::Facts.new
22+
begin
23+
req = Puppet::Indirector::Request.new(:facts, :find, 'language_server', nil, environment: current_environment)
24+
result = Puppet::Node::Facts::Facter.new.find(req)
25+
facts.from_h!(result.values)
26+
rescue StandardError => e
27+
PuppetLanguageServerSidecar.log_message(:error, "[FacterHelper::_load_facts] Error loading facts #{e.message} #{e.backtrace}")
28+
rescue LoadError => e
29+
PuppetLanguageServerSidecar.log_message(:error, "[FacterHelper::_load_facts] Error loading facts (LoadError) #{e.message} #{e.backtrace}")
30+
end
31+
32+
PuppetLanguageServerSidecar.log_message(:debug, "[FacterHelper::retrieve_facts] Finished loading #{facts.keys.count} facts")
33+
facts
34+
end
35+
end
36+
end

lib/puppet-languageserver-sidecar/puppet_modulepath_monkey_patches.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,21 @@ def modulepath
122122
result
123123
end
124124
end
125+
126+
# Inject the workspace into the facter search paths
127+
require 'puppet/indirector/facts/facter'
128+
class Puppet::Node::Facts::Facter # rubocop:disable Style/ClassAndModuleChildren
129+
class << self
130+
alias_method :original_setup_search_paths, :setup_search_paths
131+
def setup_search_paths(request)
132+
result = original_setup_search_paths(request)
133+
return result unless PuppetLanguageServerSidecar::Workspace.has_module_metadata?
134+
135+
additional_dirs = %w[lib plugins].map { |path| File.join(PuppetLanguageServerSidecar::Workspace.root_path, path, 'facter') }
136+
.select { |path| FileTest.directory?(path) }
137+
138+
return result if additional_dirs.empty?
139+
Facter.search(*additional_dirs)
140+
end
141+
end
142+
end

lib/puppet-languageserver/sidecar_protocol.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,27 @@ def list_for_object_class(klass)
520520
raise "Unknown object class #{klass.name}"
521521
end
522522
end
523+
524+
class Facts < Hash
525+
include Base
526+
527+
def from_h!(value)
528+
value.keys.each { |key| self[key] = value[key] }
529+
self
530+
end
531+
532+
def to_json(*options)
533+
::JSON.generate(to_h, options)
534+
end
535+
536+
def from_json!(json_string)
537+
obj = ::JSON.parse(json_string)
538+
obj.each do |key, value|
539+
self[key] = value
540+
end
541+
self
542+
end
543+
end
523544
end
524545
end
525546
end

lib/puppet_languageserver_sidecar.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def self.require_gems(options)
8080
puppet_parser_helper
8181
sidecar_protocol_extensions
8282
workspace
83+
facter_helper
8384
]
8485

8586
# Load files based on feature flags
@@ -117,6 +118,7 @@ def self.require_gems(options)
117118
workspace_datatypes
118119
workspace_functions
119120
workspace_types
121+
facts
120122
].freeze
121123

122124
class CommandLineParser
@@ -389,6 +391,14 @@ def self.execute(options)
389391
PuppetLanguageServerSidecar::PuppetHelper.retrieve_types(null_cache)
390392
end
391393

394+
when 'facts'
395+
# Can't cache for facts
396+
cache = PuppetLanguageServerSidecar::Cache::Null.new
397+
# Inject the workspace etc. if present
398+
injected = inject_workspace_as_module
399+
inject_workspace_as_environment unless injected
400+
PuppetLanguageServerSidecar::FacterHelper.retrieve_facts(cache)
401+
392402
else
393403
log_message(:error, "Unknown action #{options[:action]}. Expected one of #{ACTION_LIST}")
394404
end

spec/languageserver-sidecar/fixtures/real_agent/cache/facts.d/.gitkeep

Whitespace-only changes.

spec/languageserver-sidecar/fixtures/real_agent/cache/lib/facter/.gitkeep

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Facter.add('fixture_agent_custom_fact') do
2+
setcode do
3+
'fixture_agent_custom_fact_value'
4+
end
5+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
fixture_environment_external_fact: "fixture_environment_external_fact_value"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Facter.add('fixture_environment_custom_fact') do
2+
setcode do
3+
'fixture_environment_custom_fact_value'
4+
end
5+
end
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
fixture_module_external_fact: "fixture_module_external_fact_value"

0 commit comments

Comments
 (0)