Skip to content

Commit

Permalink
(GH-213) Use Facts from the Sidecar
Browse files Browse the repository at this point in the history
Now that facts can be loaded from the Sidecar, the FacterHelper needs to be
updated to use these instead of calling Facter directly.  This commit:

* Modifies the FacterHelper to call the sidecar queue to get the Fact
  information
* Modifies the FacterHelper to expose methods to query facts
* Updates the cache to store facts
* Updates the tests for the new Fact collection method
  • Loading branch information
glennsarti committed Jan 21, 2020
1 parent 2bf5940 commit a8c5e1f
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 52 deletions.
77 changes: 32 additions & 45 deletions lib/puppet-languageserver/facter_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,49 @@

module PuppetLanguageServer
module FacterHelper
@ops_lock = Mutex.new
@facts_loaded = nil

def self.reset
@ops_lock.synchronize do
_reset
end
def self.cache
PuppetLanguageServer::PuppetHelper.cache
end

def self.load_facts_async
Thread.new do
load_facts
end
def self.sidecar_queue
PuppetLanguageServer::PuppetHelper.sidecar_queue
end

# Facts
def self.facts_loaded?
@facts_loaded.nil? ? false : @facts_loaded
end

def self.load_facts
@ops_lock.synchronize do
_load_facts
end
end

def self.facts
return {} if @facts_loaded == false
@ops_lock.synchronize do
_load_facts if @fact_hash.nil?
@fact_hash.clone
end
end

# DO NOT ops_lock on any of these methods
# deadlocks will ensue!
def self._reset
@facts_loaded = nil
Facter.reset
@fact_hash = nil
end
private_class_method :_reset

def self._load_facts
_reset
@fact_hash = {}
begin
Facter.loadfacts
@fact_hash = Facter.to_hash
rescue StandardError => e
PuppetLanguageServer.log_message(:error, "[FacterHelper::_load_facts] Error loading facts #{e.message} #{e.backtrace}")
rescue LoadError => e
PuppetLanguageServer.log_message(:error, "[FacterHelper::_load_facts] Error loading facts (LoadError) #{e.message} #{e.backtrace}")
end
PuppetLanguageServer.log_message(:debug, "[FacterHelper::_load_facts] Finished loading #{@fact_hash.keys.count} facts")
def self.assert_facts_loaded
@facts_loaded = true
end
private_class_method :_load_facts

def self.load_facts
@facts_loaded = false
sidecar_queue.execute_sync('facts', [])
end

def self.load_facts_async
@facts_loaded = false
sidecar_queue.enqueue('facts', [])
end

def self.fact(name)
return nil if @facts_loaded == false
cache.object_by_name(:fact, name)
end

def self.fact_value(name)
return nil if @facts_loaded == false
object = cache.object_by_name(:fact, name)
object.nil? ? nil : object.value
end

def self.fact_names
return [] if @facts_loaded == false
cache.object_names_by_section(:fact).map(&:to_s)
end
end
end
4 changes: 2 additions & 2 deletions lib/puppet-languageserver/manifest/completion_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def self.keywords(keywords = [], &block)
end

def self.all_facts(&block)
PuppetLanguageServer::FacterHelper.facts.each_key do |name|
PuppetLanguageServer::FacterHelper.fact_names.each do |name|
item = LSP::CompletionItem.new(
'label' => name.to_s,
'insertText' => "'#{name}'",
Expand Down Expand Up @@ -206,7 +206,7 @@ def self.resolve(completion_item)
data = result.data
case data['type']
when 'variable_expr_fact'
value = PuppetLanguageServer::FacterHelper.facts[data['expr']]
value = PuppetLanguageServer::FacterHelper.fact_value(data['expr'])
# TODO: More things?
result.documentation = value.to_s

Expand Down
5 changes: 3 additions & 2 deletions lib/puppet-languageserver/manifest/hover_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ def self.get_hover_content_for_access_expression(path, expr)

# Content generation functions
def self.get_fact_content(factname)
return nil unless PuppetLanguageServer::FacterHelper.facts.key?(factname)
value = PuppetLanguageServer::FacterHelper.facts[factname]
fact = PuppetLanguageServer::FacterHelper.fact(factname)
return nil if fact.nil?
value = fact.value
content = "**#{factname}** Fact\n\n"

if value.is_a?(Hash)
Expand Down
1 change: 0 additions & 1 deletion lib/puppet-languageserver/puppet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ def self.purge_workspace
def self.sidecar_queue
@sidecar_queue_obj ||= PuppetLanguageServer::SidecarQueue.new(@helper_options)
end
private_class_method :sidecar_queue

def self.with_temporary_file(content)
tempfile = Tempfile.new('langserver-sidecar')
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet-languageserver/puppet_helper/cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module PuppetLanguageServer
module PuppetHelper
class Cache
SECTIONS = %i[class type function datatype].freeze
SECTIONS = %i[class type function datatype fact].freeze
ORIGINS = %i[default workspace bolt].freeze

def initialize(_options = {})
Expand Down
7 changes: 7 additions & 0 deletions lib/puppet-languageserver/sidecar_queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ def execute_sync(action, additional_args, handle_errors = false)

PuppetLanguageServer::PuppetHelper.assert_default_types_loaded

when 'facts'
list = PuppetLanguageServer::Sidecar::Protocol::FactList.new.from_json!(result)
@cache.import_sidecar_list!(list, :fact, :default)
PuppetLanguageServer.log_message(:debug, "SidecarQueue Thread: facts returned #{list.count} items")

PuppetLanguageServer::FacterHelper.assert_facts_loaded

when 'node_graph'
return PuppetLanguageServer::Sidecar::Protocol::NodeGraph.new.from_json!(result)

Expand Down
4 changes: 3 additions & 1 deletion spec/languageserver/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ def wait_for_puppet_loading
break if PuppetLanguageServer::PuppetHelper.default_functions_loaded? &&
PuppetLanguageServer::PuppetHelper.default_types_loaded? &&
PuppetLanguageServer::PuppetHelper.default_classes_loaded? &&
PuppetLanguageServer::PuppetHelper.default_datatypes_loaded?
PuppetLanguageServer::PuppetHelper.default_datatypes_loaded? &&
PuppetLanguageServer::FacterHelper.facts_loaded?
sleep(1)
interation += 1
next if interation < 90
raise <<-ERRORMSG
Puppet has not be initialised in time:
facts_loaded? = #{PuppetLanguageServer::FacterHelper.facts_loaded?}
functions_loaded? = #{PuppetLanguageServer::PuppetHelper.default_functions_loaded?}
types_loaded? = #{PuppetLanguageServer::PuppetHelper.default_types_loaded?}
classes_loaded? = #{PuppetLanguageServer::PuppetHelper.default_classes_loaded?}
Expand Down

0 comments on commit a8c5e1f

Please sign in to comment.