Class: Inspec::CachedFetcher

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/inspec/cached_fetcher.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, cache, opts = {}) ⇒ CachedFetcher

Returns a new instance of CachedFetcher.



9
10
11
12
13
14
15
16
17
18
# File 'lib/inspec/cached_fetcher.rb', line 9

def initialize(target, cache, opts = {})
  @target = target
  @fetcher = Inspec::Fetcher::Registry.resolve(target, opts)

  if @fetcher.nil?
    raise("Could not fetch inspec profile in #{target.inspect}.")
  end

  @cache = cache
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



8
9
10
# File 'lib/inspec/cached_fetcher.rb', line 8

def cache
  @cache
end

#fetcherObject (readonly)

Returns the value of attribute fetcher.



8
9
10
# File 'lib/inspec/cached_fetcher.rb', line 8

def fetcher
  @fetcher
end

#targetObject (readonly)

Returns the value of attribute target.



8
9
10
# File 'lib/inspec/cached_fetcher.rb', line 8

def target
  @target
end

Instance Method Details

#assert_cache_sanity!Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/inspec/cached_fetcher.rb', line 74

def assert_cache_sanity!
  return unless target.respond_to?(:key?) && target.key?(:sha256)

  exception_message = <<~EOF
    The remote source #{fetcher} no longer has the requested content:

    Request Content Hash: #{target[:sha256]}
    Actual Content Hash: #{fetcher.resolved_source[:sha256]}

    For URL, supermarket, compliance, and other sources that do not
    provide versioned artifacts, this likely means that the remote source
    has changed since your lockfile was generated.
  EOF
  raise exception_message if fetcher.resolved_source[:sha256] != target[:sha256]
end

#cache_keyObject



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/inspec/cached_fetcher.rb', line 29

def cache_key
  k = if target.is_a?(Hash)
        target[:sha256] || target[:ref]
      end

  if k.nil?
    fetcher.cache_key
  else
    k
  end
end

#fetchObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/inspec/cached_fetcher.rb', line 41

def fetch
  if cache.exists?(cache_key) && cache.locked?(cache_key)
    Inspec::Log.debug "Waiting for lock to be released on the cache dir ...."
    counter = 0
    until cache.locked?(cache_key) == false
      if (counter += 1) > 300
        Inspec::Log.warn "Giving up waiting on cache lock at #{cache_key}"
        exit 1
      end
      sleep 0.1
    end
    fetch
  elsif cache.exists?(cache_key) && !cache.locked?(cache_key)
    Inspec::Log.debug "Using cached dependency for #{target}"
    [cache.prefered_entry_for(cache_key), false]
  else
    begin
      Inspec::Log.debug "Dependency does not exist in the cache #{target}"
      cache.lock(cache.base_path_for(fetcher.cache_key)) if fetcher.requires_locking?
      fetcher.fetch(cache.base_path_for(fetcher.cache_key))
    rescue SystemExit => e
      exit_code = e.status || 1
      Inspec::Log.error "Error while creating cache for dependency ... #{e.message}"
      FileUtils.rm_rf(cache.base_path_for(fetcher.cache_key))
      exit(exit_code)
    ensure
      cache.unlock(cache.base_path_for(fetcher.cache_key)) if fetcher.requires_locking?
    end
    assert_cache_sanity!
    [fetcher.archive_path, fetcher.writable?]
  end
end

#resolved_sourceObject



20
21
22
23
# File 'lib/inspec/cached_fetcher.rb', line 20

def resolved_source
  fetch
  @fetcher.resolved_source
end

#update_from_opts(_opts) ⇒ Object



25
26
27
# File 'lib/inspec/cached_fetcher.rb', line 25

def update_from_opts(_opts)
  false
end