abide_dev_utils 0.10.1 → 0.11.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -1
- data/Gemfile.lock +25 -19
- data/Rakefile +28 -0
- data/abide_dev_utils.gemspec +1 -0
- data/lib/abide_dev_utils/cem/benchmark.rb +490 -0
- data/lib/abide_dev_utils/cem/generate/coverage_report.rb +380 -0
- data/lib/abide_dev_utils/cem/generate/reference.rb +319 -0
- data/lib/abide_dev_utils/cem/generate.rb +11 -0
- data/lib/abide_dev_utils/cem/hiera_data/mapping_data/map_data.rb +110 -0
- data/lib/abide_dev_utils/cem/hiera_data/mapping_data/mixins.rb +46 -0
- data/lib/abide_dev_utils/cem/hiera_data/mapping_data.rb +146 -0
- data/lib/abide_dev_utils/cem/hiera_data/resource_data/control.rb +127 -0
- data/lib/abide_dev_utils/cem/hiera_data/resource_data/parameters.rb +90 -0
- data/lib/abide_dev_utils/cem/hiera_data/resource_data/resource.rb +102 -0
- data/lib/abide_dev_utils/cem/hiera_data/resource_data.rb +310 -0
- data/lib/abide_dev_utils/cem/hiera_data.rb +7 -0
- data/lib/abide_dev_utils/cem/mapping/mapper.rb +282 -0
- data/lib/abide_dev_utils/cem/validate/resource_data.rb +33 -0
- data/lib/abide_dev_utils/cem/validate.rb +10 -0
- data/lib/abide_dev_utils/cem.rb +1 -0
- data/lib/abide_dev_utils/cli/cem.rb +98 -0
- data/lib/abide_dev_utils/dot_number_comparable.rb +75 -0
- data/lib/abide_dev_utils/errors/cem.rb +32 -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/class_utils.rb +1 -1
- data/lib/abide_dev_utils/ppt/code_gen/data_types.rb +64 -0
- data/lib/abide_dev_utils/ppt/code_gen/generate.rb +15 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource.rb +59 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource_types/base.rb +93 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource_types/class.rb +17 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource_types/manifest.rb +16 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource_types/parameter.rb +16 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource_types/strings.rb +13 -0
- data/lib/abide_dev_utils/ppt/code_gen/resource_types.rb +6 -0
- data/lib/abide_dev_utils/ppt/code_gen.rb +15 -0
- data/lib/abide_dev_utils/ppt/code_introspection.rb +102 -0
- data/lib/abide_dev_utils/ppt/facter_utils.rb +140 -0
- data/lib/abide_dev_utils/ppt/hiera.rb +300 -0
- data/lib/abide_dev_utils/ppt/puppet_module.rb +75 -0
- data/lib/abide_dev_utils/ppt.rb +6 -5
- data/lib/abide_dev_utils/validate.rb +14 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf/parser/helpers.rb +146 -0
- data/lib/abide_dev_utils/xccdf/parser/objects.rb +87 -144
- data/lib/abide_dev_utils/xccdf/parser.rb +5 -0
- data/lib/abide_dev_utils/xccdf/utils.rb +89 -0
- data/lib/abide_dev_utils/xccdf.rb +3 -0
- metadata +50 -3
- data/lib/abide_dev_utils/ppt/coverage.rb +0 -86
@@ -0,0 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'abide_dev_utils/ppt/code_gen/resource_types/class'
|
4
|
+
require 'abide_dev_utils/ppt/code_gen/resource_types/manifest'
|
5
|
+
require 'abide_dev_utils/ppt/code_gen/resource_types/parameter'
|
6
|
+
require 'abide_dev_utils/ppt/code_gen/resource_types/strings'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'abide_dev_utils/ppt/code_gen/data_types'
|
4
|
+
require 'abide_dev_utils/ppt/code_gen/resource'
|
5
|
+
require 'abide_dev_utils/ppt/code_gen/resource_types'
|
6
|
+
|
7
|
+
module AbideDevUtils
|
8
|
+
module Ppt
|
9
|
+
module CodeGen
|
10
|
+
def self.generate_a_manifest
|
11
|
+
Manifest.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puppet_pal'
|
4
|
+
require_relative 'code_gen/data_types'
|
5
|
+
|
6
|
+
module AbideDevUtils
|
7
|
+
module Ppt
|
8
|
+
module CodeIntrospection
|
9
|
+
class Manifest
|
10
|
+
attr_reader :manifest_file
|
11
|
+
|
12
|
+
def initialize(manifest_file)
|
13
|
+
@manifest_file = File.expand_path(manifest_file)
|
14
|
+
raise ArgumentError, "File #{@manifest_file} is not a file" unless File.file?(@manifest_file)
|
15
|
+
end
|
16
|
+
|
17
|
+
def ast
|
18
|
+
@ast ||= Puppet::Pal::Compiler.new(nil).parse_file(manifest_file)
|
19
|
+
end
|
20
|
+
|
21
|
+
def declaration
|
22
|
+
@declaration ||= Declaration.new(ast)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Declaration
|
27
|
+
include AbideDevUtils::Ppt::CodeGen::DataTypes
|
28
|
+
attr_reader :ast
|
29
|
+
|
30
|
+
def initialize(ast)
|
31
|
+
@ast = ast.definitions.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def parameters?
|
35
|
+
ast.respond_to? :parameters
|
36
|
+
end
|
37
|
+
|
38
|
+
def parameters
|
39
|
+
return unless parameters?
|
40
|
+
|
41
|
+
@parameters ||= ast.parameters.map { |p| Parameter.new(p) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Parameter
|
46
|
+
include AbideDevUtils::Ppt::CodeGen::DataTypes
|
47
|
+
attr_reader :ast
|
48
|
+
|
49
|
+
def initialize(param_ast)
|
50
|
+
@ast = param_ast
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_a(raw: false)
|
54
|
+
[type_expr(raw: raw), name(raw: raw), value(raw: raw)]
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_h(raw: false)
|
58
|
+
{
|
59
|
+
type_expr: type_expr(raw: raw),
|
60
|
+
name: name(raw: raw),
|
61
|
+
value: value(raw: raw),
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_s(raw: false)
|
66
|
+
stra = [type_expr(raw: raw), name(raw: raw)]
|
67
|
+
stra << '=' if value? && !raw
|
68
|
+
stra << value(raw: raw)
|
69
|
+
stra.compact.join(' ')
|
70
|
+
end
|
71
|
+
|
72
|
+
def name(raw: false)
|
73
|
+
return ast.name if raw
|
74
|
+
|
75
|
+
"$#{ast.name}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def value?
|
79
|
+
ast.respond_to? :value
|
80
|
+
end
|
81
|
+
|
82
|
+
def value(raw: false)
|
83
|
+
return unless value?
|
84
|
+
return ast.value if raw
|
85
|
+
|
86
|
+
display_value(ast)
|
87
|
+
end
|
88
|
+
|
89
|
+
def type_expr?
|
90
|
+
ast.respond_to? :type_expr
|
91
|
+
end
|
92
|
+
|
93
|
+
def type_expr(raw: false)
|
94
|
+
return unless type_expr?
|
95
|
+
return ast.type_expr if raw
|
96
|
+
|
97
|
+
display_type_expr(ast)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'facterdb'
|
5
|
+
|
6
|
+
module AbideDevUtils
|
7
|
+
module Ppt
|
8
|
+
# Methods relating to Facter
|
9
|
+
module FacterUtils
|
10
|
+
class << self
|
11
|
+
attr_writer :current_version
|
12
|
+
|
13
|
+
def current_version
|
14
|
+
return latest_version unless defined?(@current_version)
|
15
|
+
|
16
|
+
@current_version
|
17
|
+
end
|
18
|
+
|
19
|
+
def use_version(version)
|
20
|
+
self.current_version = version
|
21
|
+
current_version
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_version(version, reset: true)
|
25
|
+
return unless block_given?
|
26
|
+
|
27
|
+
old_ver = current_version.dup
|
28
|
+
use_version(version)
|
29
|
+
output = yield
|
30
|
+
use_version(old_ver) if reset
|
31
|
+
output
|
32
|
+
end
|
33
|
+
|
34
|
+
def fact_files
|
35
|
+
@fact_files ||= FacterDB.facterdb_fact_files.each_with_object({}) do |f, h|
|
36
|
+
facter_version = file_facter_version(f)
|
37
|
+
h[facter_version] = [] unless h.key?(facter_version)
|
38
|
+
h[facter_version] << f
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def fact_sets(facter_version: current_version)
|
43
|
+
@fact_sets ||= fact_files[facter_version].each_with_object({}) do |fp, h|
|
44
|
+
h[facter_version] = [] unless h.key?(facter_version)
|
45
|
+
h[facter_version] << JSON.parse(File.read(fp))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def file_facter_version(path)
|
50
|
+
File.basename(File.dirname(path))
|
51
|
+
end
|
52
|
+
|
53
|
+
def all_versions
|
54
|
+
@all_versions ||= fact_files.keys.sort
|
55
|
+
end
|
56
|
+
|
57
|
+
def latest_version
|
58
|
+
@latest_version ||= all_versions[-1]
|
59
|
+
end
|
60
|
+
|
61
|
+
def previous_major_version(facter_version = current_version)
|
62
|
+
@previous_major_version_map ||= {}
|
63
|
+
|
64
|
+
majver = facter_version.split('.')[0]
|
65
|
+
return @previous_major_version_map[majver] if @previous_major_version_map.key?(majver)
|
66
|
+
|
67
|
+
prev_majver = (majver.to_i - 1).to_s
|
68
|
+
prev_ver = all_versions.select { |v| v.start_with?(prev_majver) }.max
|
69
|
+
return nil if prev_ver.to_i < 1
|
70
|
+
|
71
|
+
@previous_major_version_map[majver] = prev_ver
|
72
|
+
@previous_major_version_map[majver]
|
73
|
+
end
|
74
|
+
|
75
|
+
def recurse_versions(version = current_version, &block)
|
76
|
+
use_version(version)
|
77
|
+
output = yield
|
78
|
+
return output unless output.nil? || output.empty?
|
79
|
+
|
80
|
+
prev_ver = previous_major_version(version).dup
|
81
|
+
return nil if prev_ver.nil?
|
82
|
+
|
83
|
+
recurse_versions(prev_ver, &block)
|
84
|
+
rescue SystemStackError
|
85
|
+
locals = {
|
86
|
+
prev_ver_map: @previous_major_version_map,
|
87
|
+
current_version: current_version,
|
88
|
+
}
|
89
|
+
raise "Failed to find output while recursing versions. Locals: #{locals}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def recursive_facts_for_os(os_name, os_release_major = nil, os_hardware: 'x86_64')
|
93
|
+
saved_ver = current_version.dup
|
94
|
+
output = recurse_versions do
|
95
|
+
facts_for_os(os_name, os_release_major, os_hardware: os_hardware)
|
96
|
+
end
|
97
|
+
use_version(saved_ver)
|
98
|
+
output
|
99
|
+
end
|
100
|
+
|
101
|
+
def facts_for_os(os_name, os_release_major = nil, os_hardware: 'x86_64', facter_version: current_version)
|
102
|
+
cache_key = "#{os_name.downcase}_#{os_release_major}_#{os_hardware}"
|
103
|
+
return @facts_for_os[cache_key] if @facts_for_os&.key?(cache_key)
|
104
|
+
|
105
|
+
fact_file = fact_files[facter_version].find do |f|
|
106
|
+
name_parts = File.basename(f, '.facts').split('-')
|
107
|
+
name = name_parts[0]
|
108
|
+
relmaj = name_parts.length >= 3 ? name_parts[1] : nil
|
109
|
+
hardware = name_parts[-1]
|
110
|
+
name == os_name.downcase && relmaj == os_release_major && hardware == os_hardware
|
111
|
+
end
|
112
|
+
return if fact_file.nil? || fact_file.empty?
|
113
|
+
|
114
|
+
@facts_for_os = {} unless defined?(@facts_for_os)
|
115
|
+
@facts_for_os[cache_key] = JSON.parse(File.read(fact_file))
|
116
|
+
@facts_for_os[cache_key]
|
117
|
+
end
|
118
|
+
|
119
|
+
def resolve_dot_path(dot_path, facter_version: latest_version)
|
120
|
+
path_array = dot_path.delete_prefix('facts.').split('.')
|
121
|
+
resolved = fact_sets[facter_version].map do |fs|
|
122
|
+
fs.dig(*path_array)
|
123
|
+
end
|
124
|
+
resolved.compact.uniq
|
125
|
+
end
|
126
|
+
|
127
|
+
def resolve_related_dot_paths(*dot_paths, facter_version: current_version)
|
128
|
+
resolved = []
|
129
|
+
fact_sets[facter_version].map do |fs|
|
130
|
+
resolved << dot_paths.map do |p|
|
131
|
+
path_array = p.delete_prefix('facts.').split('.')
|
132
|
+
fs.dig(*path_array)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
resolved
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,300 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'abide_dev_utils/validate'
|
5
|
+
require 'abide_dev_utils/ppt/facter_utils'
|
6
|
+
|
7
|
+
module AbideDevUtils
|
8
|
+
module Ppt
|
9
|
+
# Module for working with Hiera
|
10
|
+
module Hiera
|
11
|
+
INTERP_PATTERN = /%{([^{}]+)}/.freeze
|
12
|
+
FACT_PATTERN = /%{facts\.([^{}]+)}/.freeze
|
13
|
+
DEFAULT_FACTER_VERSION = '3.14'
|
14
|
+
DEFAULT_CONFIG_FILE = 'hiera.yaml'
|
15
|
+
|
16
|
+
def self.facter_version=(version)
|
17
|
+
@facter_version = AbideDevUtils::Ppt::FacterUtils.use_version(version.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.facter_version
|
21
|
+
@facter_version
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.default_datadir=(dir)
|
25
|
+
edir = File.expand_path(dir)
|
26
|
+
raise "Dir #{edir} not found" unless File.directory?(edir)
|
27
|
+
|
28
|
+
@default_datadir = edir
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.default_datadir
|
32
|
+
@default_datadir
|
33
|
+
end
|
34
|
+
|
35
|
+
# Represents a Hiera configuration file
|
36
|
+
class Config
|
37
|
+
def initialize(path = DEFAULT_CONFIG_FILE, facter_version: DEFAULT_FACTER_VERSION)
|
38
|
+
@path = File.expand_path(path)
|
39
|
+
raise "Hiera config file at path #{@path} not found!" unless File.file?(@path)
|
40
|
+
|
41
|
+
@root_dir = File.dirname(@path)
|
42
|
+
@conf = YAML.load_file(File.expand_path(path))
|
43
|
+
@by_name_path_store = {}
|
44
|
+
AbideDevUtils::Ppt::Hiera.facter_version = facter_version
|
45
|
+
if @conf['defaults'].key?('datadir')
|
46
|
+
AbideDevUtils::Ppt::Hiera.default_datadir = File.join(@root_dir, @conf['defaults']['datadir'])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def hierarchy
|
51
|
+
@hierarchy ||= Hierarchy.new(@conf['hierarchy'], AbideDevUtils::Ppt::Hiera.default_datadir)
|
52
|
+
end
|
53
|
+
|
54
|
+
def version
|
55
|
+
@version ||= @conf['version']
|
56
|
+
end
|
57
|
+
|
58
|
+
def defaults
|
59
|
+
@defaults ||= @conf['defaults']
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_datadir
|
63
|
+
AbideDevUtils::Ppt::Hiera.default_datadir
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_data_hash
|
67
|
+
@default_data_hash ||= defaults['data_hash']
|
68
|
+
end
|
69
|
+
|
70
|
+
def local_hiera_files(hierarchy_name: nil)
|
71
|
+
if hierarchy_name
|
72
|
+
hierarchy.entry_by_name(hierarchy_name).local_files
|
73
|
+
else
|
74
|
+
hierarchy.entries.map(&:local_files).flatten
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def local_hiera_files_with_fact(fact_str, value = nil, hierarchy_name: nil)
|
79
|
+
if hierarchy_name
|
80
|
+
hierarchy.entry_by_name(hierarchy_name).local_files_with_fact(fact_str, value)
|
81
|
+
else
|
82
|
+
hierarchy.entries.map { |e| e.local_files_with_fact(fact_str, value) }.flatten
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def local_hiera_files_with_facts(*fact_arrays, hierarchy_name: nil)
|
87
|
+
if hierarchy_name
|
88
|
+
hierarchy.entry_by_name(hierarchy_name).local_files_with_facts(*fact_arrays)
|
89
|
+
else
|
90
|
+
hierarchy.entries.map { |e| e.local_files_with_fact(*fact_arrays) }.flatten
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Represents the "hierarchy" section of the Hiera config
|
96
|
+
class Hierarchy
|
97
|
+
attr_reader :default_datadir, :entries
|
98
|
+
|
99
|
+
def initialize(hierarchy, default_datadir)
|
100
|
+
@hierarchy = hierarchy
|
101
|
+
@default_datadir = File.expand_path(default_datadir)
|
102
|
+
@entries = @hierarchy.map { |h| HierarchyEntry.new(h) }
|
103
|
+
@by_name_store = {}
|
104
|
+
@paths_by_name_store = {}
|
105
|
+
end
|
106
|
+
|
107
|
+
def method_missing(m, *args, &block)
|
108
|
+
if %i[each each_with_object each_with_index select reject map].include?(m)
|
109
|
+
@entries.send(m, *args, &block)
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def respond_to_missing?(m, include_private = false)
|
116
|
+
%i[each each_with_object each_with_index select reject map].include?(m) || super
|
117
|
+
end
|
118
|
+
|
119
|
+
def entry_by_name(name)
|
120
|
+
AbideDevUtils::Validate.populated_string(name)
|
121
|
+
return @by_name_store[name] if @by_name_store[name]
|
122
|
+
|
123
|
+
found = @entries.select { |x| x.name == name }
|
124
|
+
AbideDevUtils::Validate.not_empty(found, "Hierarchy entry for name '#{name}' not found")
|
125
|
+
@by_name_store[name] = found[0]
|
126
|
+
@by_name_store[name]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Represents a single entry in the hierarchy
|
131
|
+
class HierarchyEntry
|
132
|
+
attr_reader :entry, :name, :paths
|
133
|
+
|
134
|
+
def initialize(entry)
|
135
|
+
@entry = entry
|
136
|
+
@name = @entry['name']
|
137
|
+
@paths = @entry.key?('path') ? create_paths(@entry['path']) : create_paths(*@entry['paths'])
|
138
|
+
end
|
139
|
+
|
140
|
+
def local_files
|
141
|
+
@local_files ||= paths.map(&:local_files).flatten
|
142
|
+
end
|
143
|
+
|
144
|
+
def local_files_with_fact(fact_str, value = nil)
|
145
|
+
paths.map { |p| p.local_files_with_fact(fact_str, value) }.flatten
|
146
|
+
end
|
147
|
+
|
148
|
+
def local_files_with_facts(*fact_arrays)
|
149
|
+
paths.map { |p| p.local_files_with_facts(*fact_arrays) }.flatten
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_s
|
153
|
+
name
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def create_paths(*paths)
|
159
|
+
paths.map { |p| HierarchyEntryPath.new(p) }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Represents a Hiera entry path
|
164
|
+
class HierarchyEntryPath
|
165
|
+
attr_reader :path
|
166
|
+
|
167
|
+
def initialize(path)
|
168
|
+
@path = path
|
169
|
+
end
|
170
|
+
|
171
|
+
def path_parts
|
172
|
+
@path_parts ||= path.split('/')
|
173
|
+
end
|
174
|
+
|
175
|
+
def interpolation
|
176
|
+
@interpolation ||= path.scan(INTERP_PATTERN).flatten
|
177
|
+
end
|
178
|
+
|
179
|
+
def interpolation?
|
180
|
+
!interpolation.empty?
|
181
|
+
end
|
182
|
+
|
183
|
+
def facts
|
184
|
+
@facts ||= path.scan(FACT_PATTERN).flatten
|
185
|
+
end
|
186
|
+
|
187
|
+
def facts?
|
188
|
+
!facts.empty?
|
189
|
+
end
|
190
|
+
|
191
|
+
def possible_fact_values
|
192
|
+
@possible_fact_values ||= AbideDevUtils::Ppt::FacterUtils.resolve_related_dot_paths(*facts)
|
193
|
+
end
|
194
|
+
|
195
|
+
def local_files
|
196
|
+
@local_files ||= find_local_files.flatten
|
197
|
+
end
|
198
|
+
|
199
|
+
def local_files_with_fact(fact_str, value = nil)
|
200
|
+
local_files.select do |lf|
|
201
|
+
# The match below is case-insentive for convenience
|
202
|
+
(value.nil? ? lf.fact_values.key?(fact_str) : (lf.fact_values[fact_str]&.match?(/#{value}/i) || false))
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def local_files_with_facts(*fact_arrays)
|
207
|
+
return local_files_with_fact(*fact_arrays[0]) if fact_arrays.length == 1
|
208
|
+
|
209
|
+
start_fact = fact_arrays[0][0]
|
210
|
+
last_fact = nil
|
211
|
+
memo = {}
|
212
|
+
with_facts = []
|
213
|
+
fact_arrays.each do |fa|
|
214
|
+
cur_fact = fa[0]
|
215
|
+
memo[cur_fact] = local_files_with_fact(*fa)
|
216
|
+
if cur_fact == start_fact
|
217
|
+
with_facts = memo[cur_fact]
|
218
|
+
else
|
219
|
+
last_paths = memo[last_fact].map(&:path)
|
220
|
+
cur_paths = memo[cur_fact].map(&:path)
|
221
|
+
with_facts.reject! { |x| last_paths.difference(cur_paths).include?(x.path) }
|
222
|
+
end
|
223
|
+
last_fact = cur_fact
|
224
|
+
end
|
225
|
+
with_facts.flatten.uniq(&:path)
|
226
|
+
end
|
227
|
+
|
228
|
+
def to_s
|
229
|
+
path
|
230
|
+
end
|
231
|
+
|
232
|
+
private
|
233
|
+
|
234
|
+
def find_local_files
|
235
|
+
new_paths = []
|
236
|
+
possible_fact_values.each do |pfv|
|
237
|
+
new_path = path.dup
|
238
|
+
pfv.each do |v|
|
239
|
+
next unless v
|
240
|
+
|
241
|
+
new_path.sub!(FACT_PATTERN, v)
|
242
|
+
end
|
243
|
+
new_paths << EntryPathLocalFile.new(new_path, facts, possible_fact_values)
|
244
|
+
end
|
245
|
+
new_paths.uniq(&:path).select(&:exist?)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Represents a local file derived from a Hiera path
|
250
|
+
class EntryPathLocalFile
|
251
|
+
attr_reader :path, :facts
|
252
|
+
|
253
|
+
def initialize(path, facts, possible_fact_values)
|
254
|
+
@path = File.expand_path(File.join(AbideDevUtils::Ppt::Hiera.default_datadir, path))
|
255
|
+
@facts = facts
|
256
|
+
@possible_fact_values = possible_fact_values
|
257
|
+
end
|
258
|
+
|
259
|
+
def fact_values
|
260
|
+
@fact_values ||= fact_values_for_path
|
261
|
+
end
|
262
|
+
|
263
|
+
def path_parts
|
264
|
+
@path_parts ||= path.split('/')
|
265
|
+
end
|
266
|
+
|
267
|
+
def exist?
|
268
|
+
File.file?(path)
|
269
|
+
end
|
270
|
+
|
271
|
+
def to_s
|
272
|
+
path
|
273
|
+
end
|
274
|
+
|
275
|
+
def to_h
|
276
|
+
{
|
277
|
+
path: path,
|
278
|
+
facts: facts
|
279
|
+
}
|
280
|
+
end
|
281
|
+
|
282
|
+
private
|
283
|
+
|
284
|
+
def fact_values_for_path
|
285
|
+
no_fext_path_parts = path_parts.map { |part| File.basename(part, '.yaml') }
|
286
|
+
valid_fact_values = @possible_fact_values.select do |pfv|
|
287
|
+
pfv.all? { |v| no_fext_path_parts.include?(v) }
|
288
|
+
end
|
289
|
+
valid_fact_values.uniq! # Removes duplicate arrays, not duplicate fact values
|
290
|
+
valid_fact_values.flatten!
|
291
|
+
return {} if valid_fact_values.empty?
|
292
|
+
|
293
|
+
fact_vals = {}
|
294
|
+
facts.each_index { |idx| fact_vals[facts[idx]] = valid_fact_values[idx] }
|
295
|
+
fact_vals
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'yaml'
|
5
|
+
require 'abide_dev_utils/validate'
|
6
|
+
require 'abide_dev_utils/ppt/hiera'
|
7
|
+
|
8
|
+
module AbideDevUtils
|
9
|
+
module Ppt
|
10
|
+
# Class for working with Puppet Modules
|
11
|
+
class PuppetModule
|
12
|
+
DEF_FILES = {
|
13
|
+
metadata: 'metadata.json',
|
14
|
+
readme: 'README.md',
|
15
|
+
reference: 'REFERENCE.md',
|
16
|
+
changelog: 'CHANGELOG.md',
|
17
|
+
hiera_config: 'hiera.yaml',
|
18
|
+
fixtures: '.fixtures.yml',
|
19
|
+
rubocop: '.rubocop.yml',
|
20
|
+
sync: '.sync.yml',
|
21
|
+
pdkignore: '.pdkignore',
|
22
|
+
gitignore: '.gitignore'
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
attr_reader :directory, :special_files
|
26
|
+
|
27
|
+
def initialize(directory = Dir.pwd)
|
28
|
+
AbideDevUtils::Validate.directory(directory)
|
29
|
+
@directory = directory
|
30
|
+
@special_files = DEF_FILES.dup.transform_values { |v| File.expand_path(File.join(@directory, v)) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def name(strip_namespace: false)
|
34
|
+
strip_namespace ? metadata['name'].split('-')[-1] : metadata['name']
|
35
|
+
end
|
36
|
+
|
37
|
+
def metadata
|
38
|
+
@metadata ||= JSON.parse(File.read(special_files[:metadata]))
|
39
|
+
end
|
40
|
+
|
41
|
+
def supported_os
|
42
|
+
@supported_os ||= find_supported_os
|
43
|
+
end
|
44
|
+
|
45
|
+
def hiera_conf
|
46
|
+
@hiera_conf ||= AbideDevUtils::Ppt::Hiera::Config.new(special_files[:hiera_config])
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def find_supported_os
|
52
|
+
return [] unless metadata['operatingsystem_support']
|
53
|
+
|
54
|
+
metadata['operatingsystem_support'].each_with_object([]) do |os, arr|
|
55
|
+
os['operatingsystemrelease'].each do |r|
|
56
|
+
arr << "#{os['operatingsystem']}::#{r}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def in_dir
|
62
|
+
return unless block_given?
|
63
|
+
|
64
|
+
current = Dir.pwd
|
65
|
+
if current == File.expand_path(directory)
|
66
|
+
yield
|
67
|
+
else
|
68
|
+
Dir.chdir(directory)
|
69
|
+
yield
|
70
|
+
Dir.chdir(current)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/abide_dev_utils/ppt.rb
CHANGED
@@ -3,7 +3,13 @@
|
|
3
3
|
require 'abide_dev_utils/output'
|
4
4
|
require 'abide_dev_utils/validate'
|
5
5
|
require 'abide_dev_utils/errors'
|
6
|
+
require 'abide_dev_utils/ppt/api'
|
7
|
+
require 'abide_dev_utils/ppt/code_gen'
|
8
|
+
require 'abide_dev_utils/ppt/code_introspection'
|
6
9
|
require 'abide_dev_utils/ppt/class_utils'
|
10
|
+
require 'abide_dev_utils/ppt/facter_utils'
|
11
|
+
require 'abide_dev_utils/ppt/hiera'
|
12
|
+
require 'abide_dev_utils/ppt/puppet_module'
|
7
13
|
|
8
14
|
module AbideDevUtils
|
9
15
|
module Ppt
|
@@ -63,11 +69,6 @@ module AbideDevUtils
|
|
63
69
|
AbideDevUtils::Output.simple('Successfully fixed all classes.')
|
64
70
|
end
|
65
71
|
|
66
|
-
def self.generate_coverage_report(puppet_class_dir, hiera_path, profile = nil)
|
67
|
-
require 'abide_dev_utils/ppt/coverage'
|
68
|
-
CoverageReport.generate(puppet_class_dir, hiera_path, profile)
|
69
|
-
end
|
70
|
-
|
71
72
|
def self.build_new_object(type, name, opts)
|
72
73
|
require 'abide_dev_utils/ppt/new_obj'
|
73
74
|
AbideDevUtils::Ppt::NewObjectBuilder.new(
|
@@ -3,7 +3,12 @@
|
|
3
3
|
require 'abide_dev_utils/errors'
|
4
4
|
|
5
5
|
module AbideDevUtils
|
6
|
+
# Methods used for validating data
|
6
7
|
module Validate
|
8
|
+
def self.puppet_module_directory(path = Dir.pwd)
|
9
|
+
raise AbideDevUtils::Errors::Ppt::NotModuleDirError, path unless File.file?(File.join(path, 'metadata.json'))
|
10
|
+
end
|
11
|
+
|
7
12
|
def self.filesystem_path(path)
|
8
13
|
raise AbideDevUtils::Errors::FileNotFoundError, path unless File.exist?(path)
|
9
14
|
end
|
@@ -22,6 +27,15 @@ module AbideDevUtils
|
|
22
27
|
raise AbideDevUtils::Errors::PathNotDirectoryError, path unless File.directory?(path)
|
23
28
|
end
|
24
29
|
|
30
|
+
def self.populated_string(thing)
|
31
|
+
raise AbideDevUtils::Errors::NotPopulatedStringError, 'Object is nil' if thing.nil?
|
32
|
+
|
33
|
+
unless thing.instance_of?(String)
|
34
|
+
raise AbideDevUtils::Errors::NotPopulatedStringError, "Object is not a String. Type: #{thing.class}"
|
35
|
+
end
|
36
|
+
raise AbideDevUtils::Errors::NotPopulatedStringError, 'String is empty' if thing.empty?
|
37
|
+
end
|
38
|
+
|
25
39
|
def self.not_empty(thing, msg)
|
26
40
|
raise AbideDevUtils::Errors::ObjectEmptyError, msg if thing.empty?
|
27
41
|
end
|