mirror of
https://github.com/inspec/inspec
synced 2024-11-23 13:13:22 +00:00
Fix recursive deps for path-based deps
Signed-off-by: Steven Danna <steve@chef.io>
This commit is contained in:
parent
306688fb97
commit
34ae3122e9
11 changed files with 141 additions and 60 deletions
|
@ -10,8 +10,11 @@ module Fetchers
|
||||||
attr_reader :files
|
attr_reader :files
|
||||||
|
|
||||||
def self.resolve(target)
|
def self.resolve(target)
|
||||||
return nil unless File.exist?(target)
|
if !File.exist?(target)
|
||||||
new(target)
|
nil
|
||||||
|
else
|
||||||
|
new(target)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(target)
|
def initialize(target)
|
||||||
|
|
|
@ -6,16 +6,17 @@ require 'logger'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'molinillo'
|
require 'molinillo'
|
||||||
require 'inspec/errors'
|
require 'inspec/errors'
|
||||||
|
require 'inspec/requirement'
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class Resolver
|
class Resolver
|
||||||
def self.resolve(requirements, vendor_index, cwd, opts = {})
|
def self.resolve(requirements, vendor_index, cwd, opts = {})
|
||||||
reqs = requirements.map do |req|
|
reqs = requirements.map do |req|
|
||||||
Requirement.from_metadata(req, cwd: cwd) ||
|
req = Inspec::Requirement.from_metadata(req, cwd: cwd)
|
||||||
fail("Cannot initialize dependency: #{req}")
|
req || fail("Cannot initialize dependency: #{req}")
|
||||||
end
|
end
|
||||||
|
|
||||||
new(vendor_index, opts).resolve(reqs)
|
new(vendor_index, opts.merge(cwd: cwd)).resolve(reqs)
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(vendor_index, opts = {})
|
def initialize(vendor_index, opts = {})
|
||||||
|
@ -23,6 +24,7 @@ module Inspec
|
||||||
@debug_mode = false # TODO: hardcoded for now, grab from options
|
@debug_mode = false # TODO: hardcoded for now, grab from options
|
||||||
|
|
||||||
@vendor_index = vendor_index
|
@vendor_index = vendor_index
|
||||||
|
@cwd = opts[:cwd] || './'
|
||||||
@resolver = Molinillo::Resolver.new(self, self)
|
@resolver = Molinillo::Resolver.new(self, self)
|
||||||
@search_cache = {}
|
@search_cache = {}
|
||||||
end
|
end
|
||||||
|
@ -87,7 +89,9 @@ module Inspec
|
||||||
# @return [Array<Object>] the dependencies that are required by the given
|
# @return [Array<Object>] the dependencies that are required by the given
|
||||||
# `specification`.
|
# `specification`.
|
||||||
def dependencies_for(specification)
|
def dependencies_for(specification)
|
||||||
specification.profile.metadata.dependencies
|
specification.profile.metadata.dependencies.map do |r|
|
||||||
|
Inspec::Requirement.from_metadata(r, cwd: @cwd)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determines whether the given `requirement` is satisfied by the given
|
# Determines whether the given `requirement` is satisfied by the given
|
||||||
|
@ -208,60 +212,6 @@ module Inspec
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Requirement
|
|
||||||
attr_reader :name, :dep, :cwd, :opts
|
|
||||||
def initialize(name, dep, cwd, opts)
|
|
||||||
@name = name
|
|
||||||
@dep = Gem::Dependency.new(name, Gem::Requirement.new(Array(dep)), :runtime)
|
|
||||||
@opts = opts
|
|
||||||
@cwd = cwd
|
|
||||||
end
|
|
||||||
|
|
||||||
def matches_spec?(spec)
|
|
||||||
params = spec.profile.metadata.params
|
|
||||||
@dep.match?(params[:name], params[:version])
|
|
||||||
end
|
|
||||||
|
|
||||||
def pull
|
|
||||||
case
|
|
||||||
when @opts[:path] then pull_path(@opts[:path])
|
|
||||||
else
|
|
||||||
# TODO: should default to supermarket
|
|
||||||
fail 'You must specify the source of the dependency (for now...)'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def path
|
|
||||||
@path || pull
|
|
||||||
end
|
|
||||||
|
|
||||||
def profile
|
|
||||||
return nil if path.nil?
|
|
||||||
@profile ||= Inspec::Profile.for_target(path, {})
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.from_metadata(dep, opts)
|
|
||||||
fail 'Cannot load empty dependency.' if dep.nil? || dep.empty?
|
|
||||||
name = dep[:name] || fail('You must provide a name for all dependencies')
|
|
||||||
version = dep[:version]
|
|
||||||
new(name, version, opts[:cwd], dep)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
@dep.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def pull_path(path)
|
|
||||||
abspath = File.absolute_path(path, @cwd)
|
|
||||||
fail "Dependency path doesn't exist: #{path}" unless File.exist?(abspath)
|
|
||||||
fail "Dependency path isn't a folder: #{path}" unless File.directory?(abspath)
|
|
||||||
@path = abspath
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class SupermarketDependency
|
class SupermarketDependency
|
||||||
def initialize(url, requirement)
|
def initialize(url, requirement)
|
||||||
@url = url
|
@url = url
|
||||||
|
|
44
lib/inspec/requirement.rb
Normal file
44
lib/inspec/requirement.rb
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
module Inspec
|
||||||
|
class Requirement
|
||||||
|
attr_reader :name, :dep, :cwd, :opts
|
||||||
|
def initialize(name, version_constraints, cwd, opts)
|
||||||
|
@name = name
|
||||||
|
@dep = Gem::Dependency.new(name,
|
||||||
|
Gem::Requirement.new(Array(version_constraints)),
|
||||||
|
:runtime)
|
||||||
|
@opts = opts
|
||||||
|
@cwd = cwd
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches_spec?(spec)
|
||||||
|
params = spec.profile.metadata.params
|
||||||
|
@dep.match?(params[:name], params[:version])
|
||||||
|
end
|
||||||
|
|
||||||
|
def pull
|
||||||
|
case
|
||||||
|
when @opts[:path]
|
||||||
|
File.expand_path(@opts[:path], @cwd)
|
||||||
|
else
|
||||||
|
fail 'You must specify the source of the dependency (for now...)'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def path
|
||||||
|
@path ||= pull
|
||||||
|
end
|
||||||
|
|
||||||
|
def profile
|
||||||
|
return nil if path.nil?
|
||||||
|
@profile ||= Inspec::Profile.for_target(path, {})
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.from_metadata(dep, opts)
|
||||||
|
fail 'Cannot load empty dependency.' if dep.nil? || dep.empty?
|
||||||
|
name = dep[:name] || fail('You must provide a name for all dependencies')
|
||||||
|
version = dep[:version]
|
||||||
|
new(name, version, opts[:cwd], opts.merge(dep))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
include_controls 'profile_a'
|
||||||
|
include_controls 'profile_b'
|
|
@ -0,0 +1,12 @@
|
||||||
|
name: inheritance
|
||||||
|
title: InSpec example inheritance
|
||||||
|
maintainer: Chef Software, Inc.
|
||||||
|
copyright: Chef Software, Inc.
|
||||||
|
copyright_email: support@chef.io
|
||||||
|
license: Apache 2 license
|
||||||
|
version: 1.0.0
|
||||||
|
depends:
|
||||||
|
- name: profile_a
|
||||||
|
path: ../profile_a
|
||||||
|
- name: profile_b
|
||||||
|
path: ../profile_b
|
|
@ -0,0 +1,21 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# copyright: 2015, The Authors
|
||||||
|
# license: All rights reserved
|
||||||
|
|
||||||
|
title 'sample section'
|
||||||
|
include_controls 'profile_c'
|
||||||
|
|
||||||
|
# you can also use plain tests
|
||||||
|
describe file('/tmp') do
|
||||||
|
it { should be_directory }
|
||||||
|
end
|
||||||
|
|
||||||
|
# you add controls here
|
||||||
|
control 'tmp-1.0' do # A unique ID for this control
|
||||||
|
impact 0.7 # The criticality, if this control fails.
|
||||||
|
title 'Create /tmp directory' # A human-readable title
|
||||||
|
desc 'An optional description...'
|
||||||
|
describe file('/tmp') do # The actual test
|
||||||
|
it { should be_directory }
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
name: profile_a
|
||||||
|
title: InSpec Profile
|
||||||
|
maintainer: The Authors
|
||||||
|
copyright: The Authors
|
||||||
|
copyright_email: you@example.com
|
||||||
|
license: All Rights Reserved
|
||||||
|
summary: An InSpec Compliance Profile
|
||||||
|
version: 0.1.0
|
||||||
|
depends:
|
||||||
|
- name: profile_c
|
||||||
|
path: ../profile_c
|
|
@ -0,0 +1,20 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# copyright: 2015, The Authors
|
||||||
|
# license: All rights reserved
|
||||||
|
|
||||||
|
title 'sample section'
|
||||||
|
|
||||||
|
# you can also use plain tests
|
||||||
|
describe file('/tmp') do
|
||||||
|
it { should be_directory }
|
||||||
|
end
|
||||||
|
|
||||||
|
# you add controls here
|
||||||
|
control 'tmp-1.0' do # A unique ID for this control
|
||||||
|
impact 0.7 # The criticality, if this control fails.
|
||||||
|
title 'Create /tmp directory' # A human-readable title
|
||||||
|
desc 'An optional description...'
|
||||||
|
describe file('/tmp') do # The actual test
|
||||||
|
it { should be_directory }
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,8 @@
|
||||||
|
name: profile_b
|
||||||
|
title: InSpec Profile
|
||||||
|
maintainer: The Authors
|
||||||
|
copyright: The Authors
|
||||||
|
copyright_email: you@example.com
|
||||||
|
license: All Rights Reserved
|
||||||
|
summary: An InSpec Compliance Profile
|
||||||
|
version: 0.1.0
|
|
@ -0,0 +1,8 @@
|
||||||
|
name: profile_c
|
||||||
|
title: InSpec Profile
|
||||||
|
maintainer: The Authors
|
||||||
|
copyright: The Authors
|
||||||
|
copyright_email: you@example.com
|
||||||
|
license: All Rights Reserved
|
||||||
|
summary: An InSpec Compliance Profile
|
||||||
|
version: 0.1.0
|
Loading…
Reference in a new issue