Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for hiera datadir #86

Merged
merged 1 commit into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions lib/puppet-lint/plugins/check_ghostbuster_hiera_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ def load_data(path, content)
end

PuppetLint.new_check(:ghostbuster_hiera_files) do
def hiera
@hiera ||= YAML.load_file(ENV['HIERA_YAML_PATH'] || '/etc/puppetlabs/code/hiera.yaml')
end

def default_datadir
hiera.dig('defaults', 'datadir') || 'hieradata'
end

def path_in_datadirs?(path)
@data_dirs ||= hiera['hierarchy'].map { |h| (h['datadir'] || default_datadir).chomp('/') }.uniq
path.match?(%(./#{Regexp.union(@data_dirs)}/))
end

def regexprs
hiera_yaml_file = ENV['HIERA_YAML_PATH'] || '/etc/puppetlabs/code/hiera.yaml'
hiera = YAML.load_file(hiera_yaml_file)
regs = {}
hiera['hierarchy'].each do |hierarchy|
path_datadir = Regexp.escape((hierarchy['datadir'] || default_datadir).chomp('/'))
([*hierarchy['path']] + [*hierarchy['paths']]).each do |level|
regex = level.gsub(/%\{(::)?(trusted|server_facts|facts)\.[^\}]+\}/, '(.+)').gsub(/%\{[^\}]+\}/, '.+')
level = File.join(path_datadir, level)
regex = Regexp.new(level.gsub(/%\{(::)?(trusted|server_facts|facts)\.[^\}]+\}/, '(.+)').gsub(/%\{[^\}]+\}/, '.+'))
facts = level.match(regex).captures.map { |f| f[/%{(::)?(trusted|server_facts|facts)\.(.+)}/, 3] }
regs[regex] = facts
end
Expand All @@ -28,14 +41,14 @@ def regexprs
end

def check
return if path.match(%r{./hieradata/.*\.yaml}).nil?
return unless path_in_datadirs? path

puppetdb = PuppetGhostbuster::PuppetDB.new
_path = path.gsub('./hieradata/', '')

regexprs.each do |k, v|
m = _path.match(Regexp.new(k))
m = path.match(k)
next if m.nil?

return if m.captures.size == 0

if m.captures.size > 1
Expand Down Expand Up @@ -68,7 +81,7 @@ def check
end

notify :warning, {
message: "Hiera File #{_path} seems unused",
message: "Hiera File #{path} seems unused",
line: 1,
column: 1,
}
Expand Down
6 changes: 6 additions & 0 deletions spec/fixtures/hiera.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
---
version: 5
defaults:
datadir: data
hierarchy:
- name: "Some other location"
datadir: private/
path: "nodes/%{trusted.certname}.eyaml"

- name: "Per-node data (yaml version)"
path: "nodes/%{trusted.certname}.yaml"

Expand Down
44 changes: 34 additions & 10 deletions spec/puppet-lint/plugins/ghostbuster_hiera_files_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,95 @@

context 'with fix disabled' do
context 'when a certname file is NOT used' do
let(:path) { './hieradata/nodes/foo.example.com.yaml' }
let(:path) { './data/nodes/foo.example.com.yaml' }

it 'detects one problem' do
expect(problems.size).to eq(1)
end

it 'creates a warning' do
expect(problems).to contain_warning('Hiera File nodes/foo.example.com.yaml seems unused')
expect(problems).to contain_warning("Hiera File #{path} seems unused")
end
end

context 'when a certname file is used' do
let(:path) { './hieradata/nodes/bar.example.com.yaml' }
let(:path) { './data/nodes/bar.example.com.yaml' }

it 'does not detect any problem' do
expect(problems.size).to eq(0)
end
end

context 'when an environment file is NOT used' do
let(:path) { './hieradata/environment/foo.yaml' }
let(:path) { './data/environment/foo.yaml' }

it 'detects one problem' do
expect(problems.size).to eq(1)
end

it 'creates a warning' do
expect(problems).to contain_warning('Hiera File environment/foo.yaml seems unused')
expect(problems).to contain_warning("Hiera File #{path} seems unused")
end
end

context 'when an environment file is used' do
let(:path) { './hieradata/environment/production.yaml' }
let(:path) { './data/environment/production.yaml' }

it 'does not detect any problem' do
expect(problems.size).to eq(0)
end
end

context 'when an fact is NOT used' do
let(:path) { './hieradata/virtual/false.yaml' }
let(:path) { './data/virtual/false.yaml' }

it 'detects one problem' do
expect(problems.size).to eq(1)
end

it 'creates a warning' do
expect(problems).to contain_warning('Hiera File virtual/false.yaml seems unused')
expect(problems).to contain_warning("Hiera File #{path} seems unused")
end
end

context 'when an fact file is used' do
let(:path) { './hieradata/virtual/true.yaml' }
let(:path) { './data/virtual/true.yaml' }

it 'does not detect any problem' do
expect(problems.size).to eq(0)
end
end

context 'when an fact file is used with wrong extension' do
let(:path) { './data/virtual/true.eyaml' }

it 'detects one problem' do
expect(problems.size).to eq(1)
end

it 'creates a warning' do
expect(problems).to contain_warning("Hiera File #{path} seems unused")
end
end

context 'when using a variable in hierarchy' do
let(:path) { './hieradata/domain/example.com.yaml' }
let(:path) { './data/domain/example.com.yaml' }

it 'does not detect any problem' do
expect(problems.size).to eq(0)
end
end

context 'when hierarchy datadir is NOT default and NOT used' do
let(:path) { './private/nodes/privates.example.com.eyaml' }

it 'detects one problem' do
expect(problems.size).to eq(1)
end

it 'creates a warning' do
expect(problems).to contain_warning("Hiera File #{path} seems unused")
end
end
end
end