mirror of
https://github.com/inspec/inspec
synced 2024-11-23 21:23:29 +00:00
Add --cache
option to inspec exec
This allows users to run: inspec exec ./ --cache PATH which will use `PATH` as the dir to retrieve and store remote dependencies. The hope is that this can eventually be used with `inspec vendor PATH` to package up a profile for offline use. Signed-off-by: Steven Danna <steve@chef.io>
This commit is contained in:
parent
a63149a5b6
commit
2d28c786c3
8 changed files with 37 additions and 38 deletions
|
@ -58,6 +58,8 @@ module Inspec
|
|||
desc: 'Use colors in output.'
|
||||
option :attrs, type: :array,
|
||||
desc: 'Load attributes file (experimental)'
|
||||
option :cache, type: :string,
|
||||
desc: 'Use the given path for caching dependencies. (default: ~/.inspec/cache)'
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -102,8 +102,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|||
desc 'vendor', 'Download all dependencies and generate a lockfile'
|
||||
def vendor(path = nil)
|
||||
configure_logger(opts)
|
||||
profile = Inspec::Profile.for_target('./', opts)
|
||||
lockfile = profile.generate_lockfile(path)
|
||||
profile = Inspec::Profile.for_target('./', opts.merge(cache: Inspec::Cache.new(path)))
|
||||
lockfile = profile.generate_lockfile
|
||||
File.write('inspec.lock', lockfile.to_yaml)
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'fileutils'
|
|||
|
||||
module Inspec
|
||||
#
|
||||
# VendorIndex manages an on-disk cache of inspec profiles. The
|
||||
# Inspec::Cache manages an on-disk cache of inspec profiles. The
|
||||
# cache can contain:
|
||||
#
|
||||
# - .tar.gz profile archives
|
||||
|
@ -16,7 +16,7 @@ module Inspec
|
|||
# sources.
|
||||
#
|
||||
#
|
||||
class VendorIndex
|
||||
class Cache
|
||||
attr_reader :path
|
||||
def initialize(path = nil)
|
||||
@path = path || File.join(Dir.home, '.inspec', 'cache')
|
||||
|
@ -43,7 +43,7 @@ module Inspec
|
|||
|
||||
#
|
||||
# For a given name and source_url, return true if the
|
||||
# profile exists in the VendorIndex.
|
||||
# profile exists in the Cache.
|
||||
#
|
||||
# @param [String] name
|
||||
# @param [String] source_url
|
||||
|
@ -56,7 +56,7 @@ module Inspec
|
|||
end
|
||||
|
||||
#
|
||||
# Return the path to given profile in the vendor index.
|
||||
# Return the path to given profile in the cache.
|
||||
#
|
||||
# The `source_url` parameter should be a URI-like string that
|
||||
# fully specifies the source of the exact version we want to pull
|
|
@ -1,5 +1,4 @@
|
|||
# encoding: utf-8
|
||||
require 'inspec/dependencies/vendor_index'
|
||||
require 'inspec/dependencies/requirement'
|
||||
require 'inspec/dependencies/resolver'
|
||||
|
||||
|
@ -7,9 +6,6 @@ module Inspec
|
|||
#
|
||||
# A DependencySet manages a list of dependencies for a profile.
|
||||
#
|
||||
# Currently this class is a thin wrapper interface to coordinate the
|
||||
# VendorIndex and the Resolver.
|
||||
#
|
||||
class DependencySet
|
||||
#
|
||||
# Return a dependency set given a lockfile.
|
||||
|
@ -18,22 +14,21 @@ module Inspec
|
|||
# @param cwd [String] Current working directory for relative path includes
|
||||
# @param vendor_path [String] Path to the vendor directory
|
||||
#
|
||||
def self.from_lockfile(lockfile, cwd, vendor_path, backend)
|
||||
vendor_index = VendorIndex.new(vendor_path)
|
||||
def self.from_lockfile(lockfile, cwd, cache, backend)
|
||||
dep_tree = lockfile.deps.map do |dep|
|
||||
Inspec::Requirement.from_lock_entry(dep, cwd, vendor_index, backend)
|
||||
Inspec::Requirement.from_lock_entry(dep, cwd, cache, backend)
|
||||
end
|
||||
|
||||
dep_list = flatten_dep_tree(dep_tree)
|
||||
new(cwd, vendor_path, dep_list, backend)
|
||||
new(cwd, cache, dep_list, backend)
|
||||
end
|
||||
|
||||
def self.from_array(dependencies, cwd, vendor_path, backend)
|
||||
def self.from_array(dependencies, cwd, cache, backend)
|
||||
dep_list = {}
|
||||
dependencies.each do |d|
|
||||
dep_list[d.name] = d
|
||||
end
|
||||
new(cwd, vendor_path, dep_list, backend)
|
||||
new(cwd, cache, dep_list, backend)
|
||||
end
|
||||
|
||||
# This is experimental code to test the working of the
|
||||
|
@ -58,9 +53,9 @@ module Inspec
|
|||
# @param cwd [String] current working directory for relative path includes
|
||||
# @param vendor_path [String] path which contains vendored dependencies
|
||||
# @return [dependencies] this
|
||||
def initialize(cwd, vendor_path, dep_list, backend)
|
||||
def initialize(cwd, cache, dep_list, backend)
|
||||
@cwd = cwd
|
||||
@vendor_path = vendor_path
|
||||
@cache = cache
|
||||
@dep_list = dep_list
|
||||
@backend = backend
|
||||
end
|
||||
|
@ -91,8 +86,7 @@ module Inspec
|
|||
#
|
||||
def vendor(dependencies)
|
||||
return nil if dependencies.nil? || dependencies.empty?
|
||||
@vendor_index ||= VendorIndex.new(@vendor_path)
|
||||
@dep_list = Resolver.resolve(dependencies, @vendor_index, @cwd, @backend)
|
||||
@dep_list = Resolver.resolve(dependencies, @cache, @cwd, @backend)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,31 +9,31 @@ module Inspec
|
|||
# appropriate we delegate to Inspec::Profile directly.
|
||||
#
|
||||
class Requirement
|
||||
def self.from_metadata(dep, vendor_index, opts)
|
||||
def self.from_metadata(dep, cache, opts)
|
||||
fail 'Cannot load empty dependency.' if dep.nil? || dep.empty?
|
||||
new(dep[:name], dep[:version], vendor_index, opts[:cwd], opts.merge(dep))
|
||||
new(dep[:name], dep[:version], cache, opts[:cwd], opts.merge(dep))
|
||||
end
|
||||
|
||||
def self.from_lock_entry(entry, cwd, vendor_index, backend)
|
||||
def self.from_lock_entry(entry, cwd, cache, backend)
|
||||
req = new(entry[:name],
|
||||
entry[:version_constraints],
|
||||
vendor_index,
|
||||
cache,
|
||||
cwd,
|
||||
entry[:resolved_source].merge(backend: backend))
|
||||
|
||||
locked_deps = []
|
||||
Array(entry[:dependencies]).each do |dep_entry|
|
||||
locked_deps << Inspec::Requirement.from_lock_entry(dep_entry, cwd, vendor_index, backend)
|
||||
locked_deps << Inspec::Requirement.from_lock_entry(dep_entry, cwd, cache, backend)
|
||||
end
|
||||
req.lock_deps(locked_deps)
|
||||
req
|
||||
end
|
||||
|
||||
attr_reader :cwd, :opts, :required_version
|
||||
def initialize(name, version_constraints, vendor_index, cwd, opts)
|
||||
def initialize(name, version_constraints, cache, cwd, opts)
|
||||
@name = name
|
||||
@required_version = Gem::Requirement.new(Array(version_constraints))
|
||||
@vendor_index = vendor_index
|
||||
@cache = cache
|
||||
@backend = opts[:backend]
|
||||
@opts = opts
|
||||
@cwd = cwd
|
||||
|
@ -89,7 +89,7 @@ module Inspec
|
|||
|
||||
def dependencies
|
||||
@dependencies ||= profile.metadata.dependencies.map do |r|
|
||||
Inspec::Requirement.from_metadata(r, @vendor_index, cwd: @cwd, backend: @backend)
|
||||
Inspec::Requirement.from_metadata(r, @cache, cwd: @cwd, backend: @backend)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -99,10 +99,10 @@ module Inspec
|
|||
|
||||
def profile
|
||||
opts = @opts.dup
|
||||
opts[:cache] = @vendor_index
|
||||
opts[:cache] = @cache
|
||||
opts[:backend] = @backend
|
||||
if !@dependencies.nil?
|
||||
opts[:dependencies] = Inspec::DependencySet.from_array(@dependencies, @cwd, @vendor_index, @backend)
|
||||
opts[:dependencies] = Inspec::DependencySet.from_array(@dependencies, @cwd, @cache, @backend)
|
||||
end
|
||||
@profile ||= Inspec::Profile.for_target(opts, opts)
|
||||
end
|
||||
|
|
|
@ -23,9 +23,9 @@ module Inspec
|
|||
# implementation of the fetcher being used.
|
||||
#
|
||||
class Resolver
|
||||
def self.resolve(dependencies, vendor_index, working_dir, backend)
|
||||
def self.resolve(dependencies, cache, working_dir, backend)
|
||||
reqs = dependencies.map do |dep|
|
||||
req = Inspec::Requirement.from_metadata(dep, vendor_index, cwd: working_dir, backend: backend)
|
||||
req = Inspec::Requirement.from_metadata(dep, cache, cwd: working_dir, backend: backend)
|
||||
req || fail("Cannot initialize dependency: #{req}")
|
||||
end
|
||||
new.resolve(reqs)
|
||||
|
|
|
@ -13,7 +13,7 @@ require 'inspec/backend'
|
|||
require 'inspec/rule'
|
||||
require 'inspec/log'
|
||||
require 'inspec/profile_context'
|
||||
require 'inspec/dependencies/vendor_index'
|
||||
require 'inspec/dependencies/cache'
|
||||
require 'inspec/dependencies/lockfile'
|
||||
require 'inspec/dependencies/dependency_set'
|
||||
|
||||
|
@ -25,7 +25,7 @@ module Inspec
|
|||
# TODO: This function is getting pretty gross.
|
||||
#
|
||||
def self.resolve_target(target, cache = nil)
|
||||
cache ||= VendorIndex.new
|
||||
cache ||= Cache.new
|
||||
fetcher = Inspec::Fetcher.resolve(target)
|
||||
|
||||
if fetcher.nil?
|
||||
|
@ -88,6 +88,7 @@ EOF
|
|||
@locked_dependencies = options[:dependencies]
|
||||
@controls = options[:controls] || []
|
||||
@profile_id = options[:id]
|
||||
@cache = options[:cache] || Cache.new
|
||||
@backend = options[:backend] || Inspec::Backend.create(options)
|
||||
@source_reader = source_reader
|
||||
@tests_collected = false
|
||||
|
@ -368,14 +369,14 @@ EOF
|
|||
# @param vendor_path [String] Path to the on-disk vendor dir
|
||||
# @return [Inspec::Lockfile]
|
||||
#
|
||||
def generate_lockfile(vendor_path = nil)
|
||||
res = Inspec::DependencySet.new(cwd, vendor_path, nil, @backend)
|
||||
def generate_lockfile
|
||||
res = Inspec::DependencySet.new(cwd, @cache, nil, @backend)
|
||||
res.vendor(metadata.dependencies)
|
||||
Inspec::Lockfile.from_dependency_set(res)
|
||||
end
|
||||
|
||||
def load_dependencies
|
||||
Inspec::DependencySet.from_lockfile(lockfile, cwd, nil, @backend)
|
||||
Inspec::DependencySet.from_lockfile(lockfile, cwd, @cache, @backend)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -11,6 +11,7 @@ require 'inspec/profile_context'
|
|||
require 'inspec/profile'
|
||||
require 'inspec/metadata'
|
||||
require 'inspec/secrets'
|
||||
require 'inspec/dependencies/cache'
|
||||
# spec requirements
|
||||
|
||||
module Inspec
|
||||
|
@ -41,7 +42,7 @@ module Inspec
|
|||
@target_profiles = []
|
||||
@controls = @conf[:controls] || []
|
||||
@ignore_supports = @conf[:ignore_supports]
|
||||
|
||||
@cache = Inspec::Cache.new(@conf[:cache])
|
||||
@test_collector = @conf.delete(:test_collector) || begin
|
||||
require 'inspec/runner_rspec'
|
||||
RunnerRspec.new(@conf)
|
||||
|
@ -140,6 +141,7 @@ module Inspec
|
|||
#
|
||||
def add_target(target, _opts = [])
|
||||
profile = Inspec::Profile.for_target(target,
|
||||
cache: @cache,
|
||||
backend: @backend,
|
||||
controls: @controls,
|
||||
attributes: @conf[:attributes])
|
||||
|
|
Loading…
Reference in a new issue