Add support for relative paths to the Git fetcher

This adds support for specifying a path to a profile in a Git repo.

For example, you could have a Git repo containing multiple profiles and
you want to specify a single one like below:

```yaml
depends:
  - name: profile-1
    git: https://github.com/myorg/all-my-profiles.git
    profile_path: profiles/my-specific-profile-1
  - name: profile-2
    git: https://github.com/myorg/all-my-profiles.git
    profile_path: profiles/my-specific-profile-2
```
Signed-off-by: Jerry Aldrich <jerryaldrichiii@gmail.com>
This commit is contained in:
Jerry Aldrich 2018-10-16 21:23:27 -07:00 committed by Clinton Wolfe
parent ef14623c0a
commit 3e1d08cafe
3 changed files with 112 additions and 28 deletions

View file

@ -212,9 +212,7 @@ depends:
### git
A `git` setting specifies a profile that is located in a git repository, with optional settings for branch, tag, commit, and version. The source location is translated into a URL upon resolution. This type of dependency supports version constraints via semantic versioning as git tags.
For example:
A `git` setting specifies a profile that is located in a git repository, with optional settings for branch, tag, commit, version, and profile_path. The source location is translated into a URL upon resolution. This type of dependency supports version constraints via semantic versioning as git tags.
```YAML
depends:
@ -224,6 +222,7 @@ depends:
tag: desired_version
commit: pinned_commit
version: semver_via_tags
profile_path: optional/path/to/profile
```
### supermarket

View file

@ -37,10 +37,12 @@ module Fetchers
def initialize(remote_url, opts = {})
@branch = opts[:branch]
@profile_directory = nil
@tag = opts[:tag]
@ref = opts[:ref]
@remote_url = remote_url
@repo_directory = nil
@target_profile_path = opts[:profile_path]
end
def fetch(dir)
@ -52,23 +54,35 @@ module Fetchers
else
Dir.mktmpdir do |tmpdir|
checkout(tmpdir)
Inspec::Log.debug("Checkout of #{resolved_ref} successful. Moving checkout to #{dir}")
FileUtils.cp_r(tmpdir + "/.", @repo_directory)
if @target_profile_path
@profile_directory = dir
Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
"Moving #{@target_profile_path} to #{dir}")
target_profile = File.join(tmpdir, @target_profile_path)
FileUtils.cp_r(target_profile, dir)
else
Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
"Moving checkout to #{dir}")
FileUtils.cp_r(tmpdir + '/.', dir)
end
end
end
@repo_directory
@profile_directory || @repo_directory
end
def cache_key
resolved_ref
return resolved_ref unless @target_profile_path
OpenSSL::Digest::SHA256.hexdigest(resolved_ref + @target_profile_path)
end
def archive_path
@repo_directory
@profile_directory || @repo_directory
end
def resolved_source
{ git: @remote_url, ref: resolved_ref }
source = { git: @remote_url, ref: resolved_ref }
source[:profile_path] = @target_profile_path if @target_profile_path
source
end
private

View file

@ -7,39 +7,100 @@ describe "profiles with git-based dependencies" do
include FunctionalHelper
before(:all) do
@tmpdir = Dir.mktmpdir
@profile_dir = File.join(@tmpdir, "test-profile")
@git_dep_dir = File.join(@tmpdir, "git-dep")
@profile_dir = File.join(@tmpdir, 'test-profile')
@git_dep_dir = File.join(@tmpdir, 'git-dep')
@deep_git_dep_dir = File.join(@tmpdir, 'deep-git-dep')
Dir.chdir(@tmpdir) do
inspec("init profile git-dep")
inspec("init profile test-profile")
inspec('init profile git-dep')
inspec('init profile test-profile')
# InSpec will search directories and execute successfully if there is just
# one profile. We create two here to ensure we execute both as intended.
deep_profiles = File.join(@deep_git_dep_dir, 'profiles')
FileUtils.mkdir_p(deep_profiles)
inspec('init profile ' + File.join(deep_profiles, 'deep-profile'))
inspec('init profile ' + File.join(deep_profiles, 'another-deep-profile'))
end
Dir.chdir(@git_dep_dir) do
CMD.run_command("git init")
CMD.run_command("git add .")
CMD.run_command("git config user.name \"test\"")
CMD.run_command("git config user.email \"test@yahoo.com\"")
CMD.run_command("git commit -m \"initial commit\" --no-gpg-sign")
CMD.run_command("git commit -m \"another commit\" --allow-empty --no-gpg-sign")
CMD.run_command("git tag antag")
end
inspec_yml = YAML.load(File.read(File.join(@profile_dir, "inspec.yml")))
inspec_yml = YAML.load(File.read(File.join(@profile_dir, 'inspec.yml')))
inspec_yml["depends"] = [
{
"name" => "git-dep",
"git" => @git_dep_dir,
"tag" => "antag",
'name' => 'git-dep',
'git' => @git_dep_dir,
'tag' => 'v1.0'
},
{
'name' => 'deep-git-dep',
'git' => @deep_git_dep_dir,
'profile_path' => 'profiles/deep-profile'
},
{
'name' => 'another-deep-git-dep',
'git' => @deep_git_dep_dir,
'profile_path' => 'profiles/another-deep-profile'
}
]
File.write(File.join(@profile_dir, "inspec.yml"), YAML.dump(inspec_yml))
File.write(File.join(@profile_dir, 'inspec.yml'), YAML.dump(inspec_yml))
Dir.chdir(@git_dep_dir) do
CMD.run_command('git init')
CMD.run_command('git config user.name "testuser"')
CMD.run_command('git config user.email "testuser@example.com"')
CMD.run_command('git add .')
CMD.run_command('git commit -m "Initial commit" --no-gpg-sign')
CMD.run_command('git tag v1.0')
# Need to overwrite default test because `/tmp` does not exist on
# Windows and the default generated test checks for `/tmp`.
File.open(File.join('controls', 'example.rb'), 'w') do |f|
f.write <<~EOF
control 'example-1.0' do
describe 'value' do
it { should cmp 'value' }
end
end
EOF
end
end
Dir.chdir(@deep_git_dep_dir) do
profile_1 = File.join('profiles', 'deep-profile')
profile_2 = File.join('profiles', 'another-deep-profile')
[profile_1, profile_2].each do |profile|
# Need to overwrite default test because `/tmp` does not exist on
# Windows and the default generated test checks for `/tmp`.
File.open(File.join(profile, 'controls', 'example.rb'), 'w') do |f|
f.write <<~EOF
control '#{File.basename(profile)}-control' do
describe 'value' do
it { should cmp 'value' }
end
end
EOF
end
end
CMD.run_command('git init')
CMD.run_command('git config user.name "testuser"')
CMD.run_command('git config user.email "testuser@example.com"')
CMD.run_command('git add .')
CMD.run_command('git commit -m "Initial commit" --no-gpg-sign')
end
File.open(File.join(@profile_dir, 'controls', 'example.rb'), 'w') do |f|
f.write <<~EOF
include_controls 'git-dep'
include_controls 'deep-git-dep'
include_controls 'another-deep-git-dep'
EOF
end
end
after(:all) do
FileUtils.rm_rf(@tmpdir)
end
<<<<<<< HEAD
it "executes a profile with a git based dependency" do
out = inspec("exec #{@profile_dir} --no-create-lockfile")
@ -47,5 +108,15 @@ describe "profiles with git-based dependencies" do
out.stderr.must_equal ""
assert_exit_code 0, out
=======
it 'executes a profile with a git based dependencies' do
Dir.mktmpdir do |tmpdir|
out = inspec("exec #{@profile_dir} " \
"--no-create-lockfile " \
"--vendor-cache #{tmpdir}")
out.stderr.must_equal ''
out.exit_status.must_equal 0
end
>>>>>>> Add support for relative paths to the Git fetcher
end
end