abide_dev_utils 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -1
- data/Gemfile.lock +22 -3
- data/Rakefile +28 -0
- data/abide_dev_utils.gemspec +1 -0
- data/lib/abide_dev_utils/cem/benchmark.rb +291 -0
- data/lib/abide_dev_utils/cem/coverage_report.rb +348 -0
- data/lib/abide_dev_utils/cem/generate/reference.rb +116 -0
- data/lib/abide_dev_utils/cem/generate.rb +10 -0
- data/lib/abide_dev_utils/cem/mapping/mapper.rb +155 -0
- data/lib/abide_dev_utils/cem.rb +2 -0
- data/lib/abide_dev_utils/cli/cem.rb +80 -0
- data/lib/abide_dev_utils/errors/cem.rb +22 -0
- data/lib/abide_dev_utils/errors/general.rb +8 -2
- data/lib/abide_dev_utils/errors/ppt.rb +4 -0
- data/lib/abide_dev_utils/errors.rb +6 -0
- data/lib/abide_dev_utils/markdown.rb +104 -0
- data/lib/abide_dev_utils/ppt/facter_utils.rb +140 -0
- data/lib/abide_dev_utils/ppt/hiera.rb +297 -0
- data/lib/abide_dev_utils/ppt/puppet_module.rb +74 -0
- data/lib/abide_dev_utils/ppt.rb +3 -5
- data/lib/abide_dev_utils/validate.rb +14 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- metadata +26 -3
- data/lib/abide_dev_utils/ppt/coverage.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cf13209260261bcf509e7953d4af4a47aa7301cc7c2e8227c3d736d163cd0b1
|
4
|
+
data.tar.gz: a6d6cb52aadf58e33ce6a57d77c7921226ebb130aa2d6e4350c42c197df0f06c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be0ac34b2ee3ea116793580ef1ffff41ca4f11b41ceb6587866183734f1aee15a566b5a0063b106a18962739a1d4d7091d6e8d276dffdf6101cfcfb48afb3832
|
7
|
+
data.tar.gz: 97f9b753cb94f1a1d326eb370a59ae35d00a3c2797b6e030941e51f51e9f7713eca0af9148f9858a0f4c375273bb468ab1df928cd589903d48b9bbe7c86a92fd
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -39,6 +39,9 @@ Style/IpAddresses:
|
|
39
39
|
Exclude:
|
40
40
|
- spec/rubocop/cop/style/ip_addresses_spec.rb
|
41
41
|
|
42
|
+
Style/RegexpLiteral:
|
43
|
+
Enabled: false
|
44
|
+
|
42
45
|
Layout/EndOfLine:
|
43
46
|
EnforcedStyle: lf
|
44
47
|
|
@@ -133,4 +136,7 @@ Performance/CollectionLiteralInLoop:
|
|
133
136
|
- 'spec/**/*.rb'
|
134
137
|
|
135
138
|
RSpec/StubbedMock:
|
136
|
-
Enabled: false
|
139
|
+
Enabled: false
|
140
|
+
|
141
|
+
Convention/ExplicitBlockArgument:
|
142
|
+
Enabled: false
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
abide_dev_utils (0.
|
4
|
+
abide_dev_utils (0.11.0)
|
5
5
|
amatch (~> 0.4)
|
6
6
|
cmdparse (~> 3.0)
|
7
|
+
facterdb (>= 1.18)
|
7
8
|
google-cloud-storage (~> 1.34)
|
8
9
|
hashdiff (~> 1.0)
|
9
10
|
jira-ruby (~> 2.2)
|
@@ -62,6 +63,9 @@ GEM
|
|
62
63
|
facter (4.2.10)
|
63
64
|
hocon (~> 1.3)
|
64
65
|
thor (>= 1.0.1, < 2.0)
|
66
|
+
facterdb (1.18.0)
|
67
|
+
facter (< 5.0.0)
|
68
|
+
jgrep
|
65
69
|
faraday (2.3.0)
|
66
70
|
faraday-net_http (~> 2.0)
|
67
71
|
ruby2_keywords (>= 0.0.4)
|
@@ -120,6 +124,7 @@ GEM
|
|
120
124
|
httpclient (2.8.3)
|
121
125
|
i18n (1.10.0)
|
122
126
|
concurrent-ruby (~> 1.0)
|
127
|
+
jgrep (1.5.4)
|
123
128
|
jira-ruby (2.2.0)
|
124
129
|
activesupport
|
125
130
|
atlassian-jwt
|
@@ -138,8 +143,10 @@ GEM
|
|
138
143
|
nio4r (2.5.8)
|
139
144
|
nokogiri (1.13.6-x86_64-darwin)
|
140
145
|
racc (~> 1.4)
|
146
|
+
nokogiri (1.13.6-x86_64-linux)
|
147
|
+
racc (~> 1.4)
|
141
148
|
oauth (0.5.10)
|
142
|
-
octokit (4.
|
149
|
+
octokit (4.25.0)
|
143
150
|
faraday (>= 1, < 3)
|
144
151
|
sawyer (~> 0.9)
|
145
152
|
os (1.1.4)
|
@@ -159,6 +166,17 @@ GEM
|
|
159
166
|
coderay (~> 1.1)
|
160
167
|
method_source (~> 1.0)
|
161
168
|
public_suffix (4.0.7)
|
169
|
+
puppet (7.17.0)
|
170
|
+
concurrent-ruby (~> 1.0)
|
171
|
+
deep_merge (~> 1.0)
|
172
|
+
facter (> 2.0.1, < 5)
|
173
|
+
fast_gettext (>= 1.1, < 3)
|
174
|
+
hiera (>= 3.2.1, < 4)
|
175
|
+
locale (~> 2.1)
|
176
|
+
multi_json (~> 1.10)
|
177
|
+
puppet-resource_api (~> 1.5)
|
178
|
+
scanf (~> 1.0)
|
179
|
+
semantic_puppet (~> 1.0)
|
162
180
|
puppet (7.17.0-universal-darwin)
|
163
181
|
CFPropertyList (~> 2.2)
|
164
182
|
concurrent-ruby (~> 1.0)
|
@@ -219,7 +237,7 @@ GEM
|
|
219
237
|
ruby_parser (3.19.1)
|
220
238
|
sexp_processor (~> 4.16)
|
221
239
|
rubyzip (2.3.2)
|
222
|
-
sawyer (0.9.
|
240
|
+
sawyer (0.9.2)
|
223
241
|
addressable (>= 2.3.5)
|
224
242
|
faraday (>= 0.17.3, < 3)
|
225
243
|
scanf (1.0.0)
|
@@ -249,6 +267,7 @@ GEM
|
|
249
267
|
|
250
268
|
PLATFORMS
|
251
269
|
x86_64-darwin-19
|
270
|
+
x86_64-linux
|
252
271
|
|
253
272
|
DEPENDENCIES
|
254
273
|
abide_dev_utils!
|
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'rake'
|
3
4
|
require "bundler/gem_tasks"
|
4
5
|
require "rspec/core/rake_task"
|
5
6
|
|
@@ -10,3 +11,30 @@ require "rubocop/rake_task"
|
|
10
11
|
RuboCop::RakeTask.new
|
11
12
|
|
12
13
|
task default: %i[spec rubocop]
|
14
|
+
|
15
|
+
namespace 'cem' do
|
16
|
+
directory 'spec/fixtures'
|
17
|
+
|
18
|
+
directory 'spec/fixtures/puppetlabs-cem_linux' do
|
19
|
+
sh 'git clone git@github.com:puppetlabs/puppetlabs-cem_linux.git spec/fixtures/puppetlabs-cem_linux'
|
20
|
+
end
|
21
|
+
file 'spec/fixtures/puppetlabs-cem_linux' => ['spec/fixtures']
|
22
|
+
|
23
|
+
directory 'spec/fixtures/puppetlabs-cem_windows' do
|
24
|
+
sh 'git clone git@github.com:puppetlabs/puppetlabs-cem_windows.git spec/fixtures/puppetlabs-cem_windows'
|
25
|
+
end
|
26
|
+
file 'spec/fixtures/puppetlabs-cem_windows' => ['spec/fixtures']
|
27
|
+
|
28
|
+
task :fixture, [:cem_mod] do |_, args|
|
29
|
+
case args.cem_mod
|
30
|
+
when /linux/
|
31
|
+
Rake::Task['spec/fixtures/puppetlabs-cem_linux'].invoke
|
32
|
+
when /windows/
|
33
|
+
Rake::Task['spec/fixtures/puppetlabs-cem_windows'].invoke
|
34
|
+
else
|
35
|
+
raise "Unknown CEM module #{args.cem_mod}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
multitask fixtures: %w[spec/fixtures/puppetlabs-cem_linux spec/fixtures/puppetlabs-cem_windows]
|
40
|
+
end
|
data/abide_dev_utils.gemspec
CHANGED
@@ -41,6 +41,7 @@ Gem::Specification.new do |spec|
|
|
41
41
|
spec.add_dependency 'google-cloud-storage', '~> 1.34'
|
42
42
|
spec.add_dependency 'hashdiff', '~> 1.0'
|
43
43
|
spec.add_dependency 'amatch', '~> 0.4'
|
44
|
+
spec.add_dependency 'facterdb', '>= 1.18'
|
44
45
|
|
45
46
|
# Dev dependencies
|
46
47
|
spec.add_development_dependency 'bundler'
|
@@ -0,0 +1,291 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'abide_dev_utils/errors'
|
4
|
+
require 'abide_dev_utils/ppt/facter_utils'
|
5
|
+
require 'abide_dev_utils/cem/mapping/mapper'
|
6
|
+
|
7
|
+
module AbideDevUtils
|
8
|
+
module CEM
|
9
|
+
# Repesents a benchmark for purposes of organizing data for markdown representation
|
10
|
+
class Benchmark
|
11
|
+
attr_reader :osname, :major_version, :os_facts, :osfamily, :hiera_conf, :module_name, :framework, :rules
|
12
|
+
|
13
|
+
def initialize(osname, major_version, hiera_conf, module_name, framework: 'cis')
|
14
|
+
@osname = osname
|
15
|
+
@major_version = major_version
|
16
|
+
@os_facts = AbideDevUtils::Ppt::FacterUtils.recursive_facts_for_os(@osname, @major_version)
|
17
|
+
@osfamily = @os_facts['os']['family']
|
18
|
+
@hiera_conf = hiera_conf
|
19
|
+
@module_name = module_name
|
20
|
+
@framework = framework
|
21
|
+
@rules = {}
|
22
|
+
@map_cache = {}
|
23
|
+
@rules_in_map = {}
|
24
|
+
load_rules
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates Benchmark objects from a Puppet module
|
28
|
+
# @param pupmod [AbideDevUtils::Ppt::PuppetModule] A PuppetModule instance
|
29
|
+
# @param skip_errors [Boolean] True skips errors and loads non-erroring benchmarks, false raises the error.
|
30
|
+
# @return [Array<AbideDevUtils::CEM::Benchmark>] Array of Benchmark instances
|
31
|
+
def self.benchmarks_from_puppet_module(pupmod, ignore_all_errors: false, ignore_framework_mismatch: true)
|
32
|
+
frameworks = pupmod.hiera_conf.local_hiera_files(hierarchy_name: 'Mapping Data').each_with_object([]) do |hf, ary|
|
33
|
+
parts = hf.path.split(pupmod.hiera_conf.default_datadir)[-1].split('/')
|
34
|
+
ary << parts[2] unless ary.include?(parts[2])
|
35
|
+
end
|
36
|
+
pupmod.supported_os.each_with_object([]) do |supp_os, ary|
|
37
|
+
osname, majver = supp_os.split('::')
|
38
|
+
if majver.is_a?(Array)
|
39
|
+
majver.sort.each do |v|
|
40
|
+
frameworks.each do |fw|
|
41
|
+
benchmark = Benchmark.new(osname, v, pupmod.hiera_conf, pupmod.name(strip_namespace: true), framework: fw)
|
42
|
+
ary << benchmark
|
43
|
+
rescue StandardError => e
|
44
|
+
raise e unless ignore_all_errors || (e.instance_of?(AbideDevUtils::Errors::MappingDataFrameworkMismatchError) && ignore_framework_mismatch)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
frameworks.each do |fw|
|
49
|
+
benchmark = Benchmark.new(osname, majver, pupmod.hiera_conf, pupmod.name(strip_namespace: true), framework: fw)
|
50
|
+
ary << benchmark
|
51
|
+
rescue StandardError => e
|
52
|
+
raise e unless ignore_all_errors || (e.instance_of?(AbideDevUtils::Errors::MappingDataFrameworkMismatchError) && ignore_framework_mismatch)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def mapper
|
59
|
+
@mapper ||= AbideDevUtils::CEM::Mapping::Mapper.new(module_name, framework, load_mapping_data)
|
60
|
+
end
|
61
|
+
|
62
|
+
def map_data
|
63
|
+
mapper.map_data
|
64
|
+
end
|
65
|
+
|
66
|
+
def resource_data
|
67
|
+
@resource_data ||= load_resource_data
|
68
|
+
end
|
69
|
+
|
70
|
+
def title
|
71
|
+
mapper.title
|
72
|
+
end
|
73
|
+
|
74
|
+
def version
|
75
|
+
mapper.version
|
76
|
+
end
|
77
|
+
|
78
|
+
def title_key
|
79
|
+
@title_key ||= "#{title} #{version}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_rule(rule_hash)
|
83
|
+
@rules << rule_hash
|
84
|
+
end
|
85
|
+
|
86
|
+
def rules_in_map(mtype, level: nil, profile: nil)
|
87
|
+
real_mtype = map_type(mtype)
|
88
|
+
cache_key = [real_mtype, level, profile].compact.join('-')
|
89
|
+
return @rules_in_map[cache_key] if @rules_in_map.key?(cache_key)
|
90
|
+
|
91
|
+
all_rim = mapper.each_with_array_like(real_mtype) do |(lvl, profs), arr|
|
92
|
+
next if lvl == 'benchmark' || (!level.nil? && lvl != level)
|
93
|
+
|
94
|
+
profs.each do |prof, maps|
|
95
|
+
next if !profile.nil? && prof != profile
|
96
|
+
|
97
|
+
# CIS and STIG differ in that STIG does not have profiles
|
98
|
+
control_ids = maps.respond_to?(:keys) ? maps.keys : prof
|
99
|
+
arr << control_ids
|
100
|
+
end
|
101
|
+
end
|
102
|
+
@rules_in_map[cache_key] = all_rim.flatten.uniq
|
103
|
+
@rules_in_map[cache_key]
|
104
|
+
end
|
105
|
+
|
106
|
+
def map(control_id, level: nil, profile: nil)
|
107
|
+
mapper.get(control_id, level: level, profile: profile)
|
108
|
+
end
|
109
|
+
|
110
|
+
def map_type(control_id)
|
111
|
+
mapper.map_type(control_id)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def load_rules
|
117
|
+
resource_data["#{module_name}::resources"].each do |_, rdata|
|
118
|
+
unless rdata.key?('controls')
|
119
|
+
puts "Controls key not found in #{rdata}"
|
120
|
+
next
|
121
|
+
end
|
122
|
+
rdata['controls'].each do |control, control_data|
|
123
|
+
rule_title = map(control)
|
124
|
+
next if rule_title.nil? || rule_title.empty?
|
125
|
+
|
126
|
+
rule_title.find { |id| map_type(id) == 'title' }
|
127
|
+
alternate_ids = map(rule_title)
|
128
|
+
|
129
|
+
next unless rule_title.is_a?(String)
|
130
|
+
|
131
|
+
@rules[rule_title] = {} unless @rules&.key?(rule_title)
|
132
|
+
@rules[rule_title]['number'] = alternate_ids.find { |id| map_type(id) == 'number' }
|
133
|
+
@rules[rule_title]['alternate_ids'] = alternate_ids
|
134
|
+
@rules[rule_title]['params'] = [] unless @rules[rule_title].key?('params')
|
135
|
+
@rules[rule_title]['level'] = [] unless @rules[rule_title].key?('level')
|
136
|
+
@rules[rule_title]['profile'] = [] unless @rules[rule_title].key?('profile')
|
137
|
+
param_hashes(control_data).each do |param_hash|
|
138
|
+
next if @rules[rule_title]['params'].include?(param_hash[:name])
|
139
|
+
|
140
|
+
@rules[rule_title]['params'] << param_hash
|
141
|
+
end
|
142
|
+
levels, profiles = find_levels_and_profiles(control)
|
143
|
+
unless @rules[rule_title]['level'] == levels
|
144
|
+
@rules[rule_title]['level'] = @rules[rule_title]['level'] | levels
|
145
|
+
end
|
146
|
+
unless @rules[rule_title]['profile'] == profiles
|
147
|
+
@rules[rule_title]['profile'] = @rules[rule_title]['profile'] | profiles
|
148
|
+
end
|
149
|
+
@rules[rule_title]['resource'] = rdata['type']
|
150
|
+
end
|
151
|
+
end
|
152
|
+
@rules = sort_rules
|
153
|
+
end
|
154
|
+
|
155
|
+
def param_hashes(control_data)
|
156
|
+
return [] if control_data.nil? || control_data.empty?
|
157
|
+
|
158
|
+
p_hashes = []
|
159
|
+
if !control_data.respond_to?(:each) && control_data == 'no_params'
|
160
|
+
p_hashes << no_params
|
161
|
+
else
|
162
|
+
control_data.each do |param, param_val|
|
163
|
+
p_hashes << {
|
164
|
+
name: param,
|
165
|
+
type: ruby_class_to_puppet_type(param_val.class.to_s),
|
166
|
+
default: param_val,
|
167
|
+
}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
p_hashes
|
171
|
+
end
|
172
|
+
|
173
|
+
def no_params
|
174
|
+
{ name: 'No parameters', type: nil, default: nil }
|
175
|
+
end
|
176
|
+
|
177
|
+
# We sort the rules by their control number so they
|
178
|
+
# appear in the REFERENCE in benchmark order
|
179
|
+
def sort_rules
|
180
|
+
sorted = @rules.dup.sort_by do |_, v|
|
181
|
+
control_num_to_int(v['number'])
|
182
|
+
end
|
183
|
+
sorted.to_h
|
184
|
+
end
|
185
|
+
|
186
|
+
# In order to sort the rules by their control number,
|
187
|
+
# we need to convert the control number to an integer.
|
188
|
+
# This is a rough conversion, but should be sufficient
|
189
|
+
# for the purposes of sorting. The multipliers are
|
190
|
+
# the 20th, 15th, 10th, and 5th numbers in the Fibonacci
|
191
|
+
# sequence, then 1 after that. The reason for this is to
|
192
|
+
# ensure a "spiraled" wieghting of the sections in the control
|
193
|
+
# number, with 1st section having the most sorting weight, 2nd
|
194
|
+
# having second most, etc. However, the differences in the multipliers
|
195
|
+
# are such that it would be difficult for the product of a lesser-weighted
|
196
|
+
# section to be greater than a greater-weighted section.
|
197
|
+
def control_num_to_int(control_num)
|
198
|
+
multipliers = [6765, 610, 55, 5, 1]
|
199
|
+
nsum = 0
|
200
|
+
midx = 0
|
201
|
+
control_num.split('.').each do |num|
|
202
|
+
multiplier = midx >= multipliers.length ? 1 : multipliers[midx]
|
203
|
+
nsum += num.to_i * multiplier
|
204
|
+
midx += 1
|
205
|
+
end
|
206
|
+
nsum
|
207
|
+
end
|
208
|
+
|
209
|
+
def find_levels_and_profiles(control_id)
|
210
|
+
levels = []
|
211
|
+
profiles = []
|
212
|
+
mapper.each_like(control_id) do |lvl, profile_hash|
|
213
|
+
next if lvl == 'benchmark'
|
214
|
+
|
215
|
+
profile_hash.each do |prof, _|
|
216
|
+
unless map(control_id, level: lvl, profile: prof).nil?
|
217
|
+
levels << lvl
|
218
|
+
profiles << prof
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
[levels, profiles]
|
223
|
+
end
|
224
|
+
|
225
|
+
def ruby_class_to_puppet_type(class_name)
|
226
|
+
pup_type = class_name.split('::').last.capitalize
|
227
|
+
case pup_type
|
228
|
+
when %r{(Trueclass|Falseclass)}
|
229
|
+
'Boolean'
|
230
|
+
when %r{(String|Pathname)}
|
231
|
+
'String'
|
232
|
+
when %r{(Integer|Fixnum)}
|
233
|
+
'Integer'
|
234
|
+
when %r{(Float|Double)}
|
235
|
+
'Float'
|
236
|
+
else
|
237
|
+
pup_type
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def load_mapping_data
|
242
|
+
files = case module_name
|
243
|
+
when /_windows$/
|
244
|
+
cem_windows_mapping_files
|
245
|
+
when /_linux$/
|
246
|
+
cem_linux_mapping_files
|
247
|
+
else
|
248
|
+
raise "Module name '#{module_name}' is not a CEM module"
|
249
|
+
end
|
250
|
+
validate_mapping_files_framework(files).each_with_object({}) do |f, h|
|
251
|
+
next unless f.path.include?(framework)
|
252
|
+
|
253
|
+
h[File.basename(f.path, '.yaml')] = YAML.load_file(f.path)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def cem_linux_mapping_files
|
258
|
+
facts = [['os.name', osname], ['os.release.major', major_version]]
|
259
|
+
mapping_files = hiera_conf.local_hiera_files_with_facts(*facts, hierarchy_name: 'Mapping Data')
|
260
|
+
raise AbideDevUtils::Errors::MappingFilesNotFoundError, facts if mapping_files.nil? || mapping_files.empty?
|
261
|
+
|
262
|
+
mapping_files
|
263
|
+
end
|
264
|
+
|
265
|
+
def cem_windows_mapping_files
|
266
|
+
facts = ['os.release.major', major_version]
|
267
|
+
mapping_files = hiera_conf.local_hiera_files_with_fact(facts[0], facts[1], hierarchy_name: 'Mapping Data')
|
268
|
+
raise AbideDevUtils::Errors::MappingFilesNotFoundError, facts if mapping_files.nil? || mapping_files.empty?
|
269
|
+
|
270
|
+
mapping_files
|
271
|
+
end
|
272
|
+
|
273
|
+
def validate_mapping_files_framework(files)
|
274
|
+
validated_files = files.select { |f| f.path_parts.include?(framework) }
|
275
|
+
if validated_files.nil? || validated_files.empty?
|
276
|
+
raise AbideDevUtils::Errors::MappingDataFrameworkMismatchError, framework
|
277
|
+
end
|
278
|
+
|
279
|
+
validated_files
|
280
|
+
end
|
281
|
+
|
282
|
+
def load_resource_data
|
283
|
+
facts = [['os.family', osfamily], ['os.name', osname], ['os.release.major', major_version]]
|
284
|
+
rdata_files = hiera_conf.local_hiera_files_with_facts(*facts, hierarchy_name: 'Resource Data')
|
285
|
+
raise AbideDevUtils::Errors::ResourceDataNotFoundError, facts if rdata_files.nil? || rdata_files.empty?
|
286
|
+
|
287
|
+
YAML.load_file(rdata_files[0].path)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|