abide_dev_utils 0.4.2 → 0.8.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +1 -1
  4. data/CODEOWNERS +1 -0
  5. data/README.md +34 -0
  6. data/abide_dev_utils.gemspec +11 -7
  7. data/itests.rb +138 -0
  8. data/lib/abide_dev_utils/cli/abstract.rb +2 -0
  9. data/lib/abide_dev_utils/cli/comply.rb +115 -0
  10. data/lib/abide_dev_utils/cli/jira.rb +2 -2
  11. data/lib/abide_dev_utils/cli/puppet.rb +136 -11
  12. data/lib/abide_dev_utils/cli/xccdf.rb +26 -7
  13. data/lib/abide_dev_utils/cli.rb +2 -0
  14. data/lib/abide_dev_utils/comply.rb +498 -0
  15. data/lib/abide_dev_utils/config.rb +19 -0
  16. data/lib/abide_dev_utils/errors/comply.rb +17 -0
  17. data/lib/abide_dev_utils/errors/gcloud.rb +27 -0
  18. data/lib/abide_dev_utils/errors/general.rb +5 -0
  19. data/lib/abide_dev_utils/errors/ppt.rb +12 -0
  20. data/lib/abide_dev_utils/errors/xccdf.rb +8 -0
  21. data/lib/abide_dev_utils/errors.rb +2 -0
  22. data/lib/abide_dev_utils/gcloud.rb +22 -0
  23. data/lib/abide_dev_utils/jira.rb +15 -0
  24. data/lib/abide_dev_utils/mixins.rb +16 -0
  25. data/lib/abide_dev_utils/output.rb +7 -3
  26. data/lib/abide_dev_utils/ppt/api.rb +219 -0
  27. data/lib/abide_dev_utils/ppt/class_utils.rb +184 -0
  28. data/lib/abide_dev_utils/ppt/coverage.rb +2 -3
  29. data/lib/abide_dev_utils/ppt/score_module.rb +162 -0
  30. data/lib/abide_dev_utils/ppt.rb +138 -49
  31. data/lib/abide_dev_utils/validate.rb +5 -1
  32. data/lib/abide_dev_utils/version.rb +1 -1
  33. data/lib/abide_dev_utils/xccdf.rb +567 -9
  34. data/lib/abide_dev_utils.rb +1 -0
  35. metadata +82 -17
  36. data/lib/abide_dev_utils/utils/general.rb +0 -9
  37. data/lib/abide_dev_utils/xccdf/cis/hiera.rb +0 -161
  38. data/lib/abide_dev_utils/xccdf/cis.rb +0 -3
@@ -1,66 +1,155 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'abide_dev_utils/ppt/coverage'
4
- require 'abide_dev_utils/ppt/new_obj'
3
+ require 'abide_dev_utils/output'
4
+ require 'abide_dev_utils/validate'
5
+ require 'abide_dev_utils/errors'
6
+ require 'abide_dev_utils/ppt/class_utils'
5
7
 
6
8
  module AbideDevUtils
7
9
  module Ppt
8
- # Given a directory holding Puppet manifests, returns
9
- # the full namespace for all classes in that directory.
10
- # @param puppet_class_dir [String] path to a dir containing Puppet manifests
11
- # @return [String] The namespace for all classes in manifests in the dir
12
- def self.find_class_namespace(puppet_class_dir)
13
- path = Pathname.new(puppet_class_dir)
14
- mod_root = nil
15
- ns_parts = []
16
- found_manifests = false
17
- path.ascend do |p|
18
- if found_manifests
19
- mod_root = find_mod_root(p)
20
- break
21
- end
22
- if File.basename(p) == 'manifests'
23
- found_manifests = true
24
- next
25
- else
26
- ns_parts << File.basename(p)
27
- end
10
+ # Renames a Puppet class by renaming the class declaration and class file
11
+ # @param from [String] fully-namespaced existing Puppet class name
12
+ # @param to [String] fully-namespaced new Puppet class name
13
+ def self.rename_puppet_class(from, to, **kwargs)
14
+ from_path = ClassUtils.path_from_class_name(from)
15
+ to_path = ClassUtils.path_from_class_name(to)
16
+ file_path = kwargs.fetch(:declaration_in_to_file, false) ? to_path : from_path
17
+ raise ClassFileNotFoundError, "Path:#{file_path}" if !File.file?(file_path) && kwargs.fetch(:validate_path, true)
18
+
19
+ rename_puppet_class_declaration(from, to, file_path, **kwargs)
20
+ AbideDevUtils::Output.simple("Renamed #{from} to #{to} at #{file_path}.")
21
+ return unless kwargs.fetch(:declaration_only, false)
22
+
23
+ rename_class_file(from_path, to_path, **kwargs)
24
+ AbideDevUtils::Output.simple("Renamed file #{from_path} to #{to_path}.")
25
+ end
26
+
27
+ def self.audit_class_names(dir, **kwargs)
28
+ mismatched = ClassUtils.find_all_mismatched_class_declarations(dir)
29
+ outfile = kwargs.key?(:file) ? File.open(kwargs[:file], 'a') : nil
30
+ quiet = kwargs.fetch(:quiet, false)
31
+ mismatched.each do |class_file|
32
+ AbideDevUtils::Output.simple("Mismatched class name in file #{class_file}") unless quiet
33
+ outfile << "MISMATCHED_CLASS_NAME: #{class_file}\n" unless outfile.nil?
28
34
  end
29
- "#{mod_root}::#{ns_parts.reverse.join('::')}::"
35
+ outfile&.close
36
+ AbideDevUtils::Output.simple("Found #{mismatched.length} mismatched classes in #{dir}.") unless quiet
37
+ ensure
38
+ outfile&.close
30
39
  end
31
40
 
32
- # Given a Pathname object of the 'manifests' directory in a Puppet module,
33
- # determines the module namespace root. Does this by consulting
34
- # metadata.json, if it exists, or by using the parent directory name.
35
- # @param pathname [Pathname] A Pathname object of the module's manifests dir
36
- # @return [String] The module's namespace root
37
- def self.find_mod_root(pathname)
38
- metadata_file = nil
39
- pathname.entries.each do |e|
40
- metadata_file = "#{pathname}/metadata.json" if File.basename(e) == 'metadata.json'
41
+ def self.fix_class_names_file_rename(dir, **kwargs)
42
+ mismatched = ClassUtils.find_all_mismatched_class_declarations(dir)
43
+ progress = AbideDevUtils::Output.progress(title: 'Renaming files', total: mismatched.length)
44
+ mismatched.each do |class_path|
45
+ should = ClassUtils.path_from_class_name(class_name_from_declaration(class_path))
46
+ ClassUtils.rename_class_file(class_path, should, **kwargs)
47
+ progress.increment
48
+ AbideDevUtils::Output.simple("Renamed file #{class_path} to #{should}...") if kwargs.fetch(:verbose, false)
41
49
  end
42
- if metadata_file.nil?
43
- File.basename(p)
44
- else
45
- File.open(metadata_file) do |f|
46
- file = JSON.parse(f.read)
47
- File.basename(p) unless file.key?('name')
48
- file['name'].split('-')[-1]
49
- end
50
+ AbideDevUtils::Output.simple('Successfully fixed all classes.')
51
+ end
52
+
53
+ def self.fix_class_names_class_rename(dir, **kwargs)
54
+ mismatched = ClassUtils.find_all_mismatched_class_declarations(dir)
55
+ progress = AbideDevUtils::Output.progress(title: 'Renaming classes', total: mismatched.length)
56
+ mismatched.each do |class_path|
57
+ current = ClassUtils.class_name_from_declaration(class_path)
58
+ should = ClassUtils.class_name_from_path(class_path)
59
+ ClassUtils.rename_puppet_class_declaration(current, should, class_path, **kwargs)
60
+ progress.increment
61
+ AbideDevUtils::Output.simple("Renamed #{from} to #{to} at #{file_path}...") if kwargs.fetch(:verbose, false)
62
+ end
63
+ AbideDevUtils::Output.simple('Successfully fixed all classes.')
64
+ end
65
+
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
+ def self.build_new_object(type, name, opts)
72
+ require 'abide_dev_utils/ppt/new_obj'
73
+ AbideDevUtils::Ppt::NewObjectBuilder.new(
74
+ type,
75
+ name,
76
+ opts: opts,
77
+ vars: opts.fetch(:vars, '').split(',').map { |i| i.split('=') }.to_h # makes the str a hash
78
+ ).build
79
+ end
80
+
81
+ def self.add_cis_comment(path, xccdf, number_format: false)
82
+ require 'abide_dev_utils/xccdf'
83
+
84
+ parsed_xccdf = AbideDevUtils::XCCDF::Benchmark.new(xccdf)
85
+ return add_cis_comment_to_all(path, parsed_xccdf, number_format: number_format) if File.directory?(path)
86
+ return add_cis_comment_to_single(path, parsed_xccdf, number_format: number_format) if File.file?(path)
87
+
88
+ raise AbideDevUtils::Errors::FileNotFoundError, path
89
+ end
90
+
91
+ def self.add_cis_comment_to_single(path, xccdf, number_format: false)
92
+ write_cis_comment_to_file(
93
+ path,
94
+ cis_recommendation_comment(
95
+ path,
96
+ xccdf,
97
+ number_format
98
+ )
99
+ )
100
+ end
101
+
102
+ def self.add_cis_comment_to_all(path, xccdf, number_format: false)
103
+ comments = {}
104
+ Dir[File.join(path, '*.pp')].each do |puppet_file|
105
+ comment = cis_recommendation_comment(puppet_file, xccdf, number_format)
106
+ comments[puppet_file] = comment unless comment.nil?
107
+ end
108
+ comments.each do |key, value|
109
+ write_cis_comment_to_file(key, value)
50
110
  end
111
+ AbideDevUtils::Output.simple('Successfully added comments.')
51
112
  end
52
113
 
53
- # @return [Array] An array of frozen arrays where each sub-array's
54
- # index 0 is class_name and index 1 is the full path to the file.
55
- def self.find_all_classes_and_paths(puppet_class_dir)
56
- all_cap = []
57
- Dir.each_child(puppet_class_dir) do |c|
58
- path = "#{puppet_class_dir}/#{c}"
59
- next if File.directory?(path) || File.extname(path) != '.pp'
114
+ def self.write_cis_comment_to_file(path, comment)
115
+ require 'tempfile'
116
+ tempfile = Tempfile.new
117
+ begin
118
+ File.open(tempfile, 'w') do |nf|
119
+ nf.write("#{comment}\n")
120
+ File.foreach(path) do |line|
121
+ nf.write(line) unless line == "#{comment}\n"
122
+ end
123
+ end
124
+ File.rename(path, "#{path}.old")
125
+ tempfile.close
126
+ File.rename(tempfile.path, path)
127
+ File.delete("#{path}.old")
128
+ AbideDevUtils::Output.simple("Added CIS recomendation comment to #{path}...")
129
+ ensure
130
+ tempfile.close
131
+ tempfile.unlink
132
+ end
133
+ end
60
134
 
61
- all_cap << [File.basename(path, '.pp'), path].freeze
135
+ def self.cis_recommendation_comment(puppet_file, xccdf, number_format)
136
+ _, control = xccdf.find_cis_recommendation(
137
+ File.basename(puppet_file, '.pp'),
138
+ number_format: number_format
139
+ )
140
+ if control.nil?
141
+ AbideDevUtils::Output.simple("Could not find recommendation text for #{puppet_file}...")
142
+ return nil
62
143
  end
63
- all_cap
144
+ control_title = xccdf.resolve_control_reference(control).xpath('./xccdf:title').text
145
+ "# #{control_title}"
146
+ end
147
+
148
+ def self.score_module(module_path, outfile: nil, quiet: false, checks: ['all'], **_)
149
+ AbideDevUtils::Output.simple 'This command is not currently implemented'
150
+ # require 'abide_dev_utils/ppt/score_module'
151
+ # score = {}
152
+ # score[:lint_check] = ScoreModule.lint if checks.include?('all') || checks.include?('lint')
64
153
  end
65
154
  end
66
155
  end
@@ -8,9 +8,13 @@ module AbideDevUtils
8
8
  raise AbideDevUtils::Errors::FileNotFoundError, path unless File.exist?(path)
9
9
  end
10
10
 
11
- def self.file(path)
11
+ def self.file(path, extension: nil)
12
12
  filesystem_path(path)
13
13
  raise AbideDevUtils::Errors::PathNotFileError, path unless File.file?(path)
14
+ return if extension.nil?
15
+
16
+ file_ext = extension.match?(/^\.[A-Za-z0-9]+$/) ? extension : ".#{extension}"
17
+ raise AbideDevUtils::Errors::FileExtensionIncorrectError, extension unless File.extname(path) == file_ext
14
18
  end
15
19
 
16
20
  def self.directory(path)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.4.2"
4
+ VERSION = "0.8.0"
5
5
  end