Skip to content

Commit

Permalink
add filter_command (e.g. for gpg signature validation) (git only) (#823)
Browse files Browse the repository at this point in the history
* add filter_command directive (git only)

* Update CHANGELOG.mkd

Co-authored-by: Ben Ford <ben.ford@puppetlabs.com>
  • Loading branch information
mhumpula and binford2k authored Jul 22, 2020
1 parent bbe534a commit 2eb088a
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ CHANGELOG
=========

Unreleased
----------
## Changes

(#823) Add filter_command configuration option for git repositories
(Thanks to [mhumpula](https://github.com/mhumpula) for the [feature](https://github.com/puppetlabs/r10k/pull/823/conflicts).)

----

3.5.2
Expand Down
23 changes: 23 additions & 0 deletions doc/dynamic-environments/configuration.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,29 @@ sources:
- 'dev'
```

### filter_command

You can filter out any branch based on the result of the command specified as
'filter_command'. Currently it only works with git repository. Non zero return
status of the command results in a branch beeing removed. The command is passed
additional environment variables

* GIT_DIR – path to the cached git repository
* R10K_BRANCH – branch which is being filtered
* R10K_NAME – source name from r10k configuration

This can be used for example for filtering out the branches with invalid gpg signature of their latest commit

```yaml
---
sources:
mysource:
basedir: '/etc/puppet/environments'
filter_command: 'git verify-commit $R10K_BRANCH 2> /dev/null'
```

Beware that if the production branch of manifests is filtered out, you will end up with empty environment.

Examples
--------

Expand Down
24 changes: 22 additions & 2 deletions lib/r10k/source/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class R10K::Source::Git < R10K::Source::Base
# that will be deployed as environments.
attr_reader :ignore_branch_prefixes

# @!attribute [r] filter_command
# @return [String] Command to run to filter branches
attr_reader :filter_command

# Initialize the given source.
#
# @param name [String] The identifier for this source.
Expand All @@ -61,6 +65,7 @@ def initialize(name, basedir, options = {})
@remote = options[:remote]
@invalid_branches = (options[:invalid_branches] || 'correct_and_warn')
@ignore_branch_prefixes = options[:ignore_branch_prefixes]
@filter_command = options[:filter_command]

@cache = R10K::Git.cache.generate(@remote)
end
Expand Down Expand Up @@ -115,7 +120,7 @@ def desired_contents
environments.map {|env| env.dirname }
end

def filter_branches(branches, ignore_prefixes)
def filter_branches_by_regexp(branches, ignore_prefixes)
filter = Regexp.new("^#{Regexp.union(ignore_prefixes)}")
branches = branches.reject do |branch|
result = filter.match(branch)
Expand All @@ -127,14 +132,29 @@ def filter_branches(branches, ignore_prefixes)
branches
end

def filter_branches_by_command(branches, command)
branches.select do |branch|
result = system({'GIT_DIR' => @cache.git_dir.to_s, 'R10K_BRANCH' => branch, 'R10K_NAME' => @name.to_s}, command)
unless result
logger.warn _("Branch `%{name}:%{branch}` filtered out by filter_command %{cmd}") % {name: @name, branch: branch, cmd: command}
end
result
end
end

private

def branch_names
opts = {:prefix => @prefix, :invalid => @invalid_branches, :source => @name}
branches = @cache.branches
if @ignore_branch_prefixes && !@ignore_branch_prefixes.empty?
branches = filter_branches(branches, @ignore_branch_prefixes)
branches = filter_branches_by_regexp(branches, @ignore_branch_prefixes)
end

if @filter_command && !@filter_command.empty?
branches = filter_branches_by_command(branches, @filter_command)
end

branches.map do |branch|
R10K::Environment::Name.new(branch, opts)
end
Expand Down
38 changes: 37 additions & 1 deletion spec/unit/source/git_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,45 @@
let(:ignore_prefixes) { ['dev', 'test'] }

it "filters branches" do
expect(subject.filter_branches(branches, ignore_prefixes)).to eq(['master', 'production', 'not_dev_test_me'])
expect(subject.filter_branches_by_regexp(branches, ignore_prefixes)).to eq(['master', 'production', 'not_dev_test_me'])
end
end

describe "filtering branches with command" do
let(:branches) { ['master', 'development', 'production'] }
let(:filter_command) { 'sh -c "[ $R10K_BRANCH != development ]"' }

it "filters branches" do
expect(subject.filter_branches_by_command(branches, filter_command)).to eq(['master', 'production'])
end
end

describe "generate_environments respects filter_command setting" do
before do
allow(subject.cache).to receive(:branches).and_return ['master', 'development', 'production']
subject.instance_variable_set(:@filter_command, '[ $R10K_BRANCH != master ]')
end

let(:environments) { subject.generate_environments }

it "creates an environment for each branch not filtered by filter_command" do
expect(subject.generate_environments.size).to eq(2)
end
end

describe "generate_environments respects filter_command setting and name" do
before do
allow(subject.cache).to receive(:branches).and_return ['master', 'development', 'production']
subject.instance_variable_set(:@filter_command, '[ $R10K_NAME = mysource ]')
end

let(:environments) { subject.generate_environments }

it "creates an environment for each branch not filtered by filter_command" do
expect(subject.generate_environments.size).to eq(3)
end
end

end

describe R10K::Source::Git, "handling invalid branch names" do
Expand Down

0 comments on commit 2eb088a

Please sign in to comment.