cps-property-generator 0.2.17 → 0.3.1

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.
@@ -1,27 +1,32 @@
1
1
  require_relative '../helpers/helpers'
2
+
2
3
  module PropertyGenerator
3
4
  require 'yaml'
5
+ require 'pathname'
4
6
  class GlobalsLinter
7
+ TESTS = [
8
+ 'globals_load_as_hashes',
9
+ 'globals_are_defined_for_valid_environemnts'
10
+ ].freeze
5
11
 
6
- def initialize(path, configs)
12
+ def initialize(path, configs, ignored_tests)
7
13
  @configs = configs
8
14
  @globals = {}
15
+ @ignored_tests = ignored_tests
9
16
  valid_paths = PropertyGenerator.valid_paths(path)
10
17
  valid_paths.each do |file_path|
11
- @globals[file_path] = YAML.load_file(file_path)
18
+ @globals[file_path] = YAML.load_file(file_path)
12
19
  end
13
20
  end
14
21
 
15
22
  def run_globals_tests
16
- tests = ['globals_load_as_hashes',
17
- 'globals_are_defined_for_valid_environemnts',
18
- ]
19
- results = PropertyGenerator.test_runner(self, tests)
20
- results
23
+ tests = TESTS - @ignored_tests
24
+
25
+ PropertyGenerator.test_runner(self, tests)
21
26
  end
22
27
 
23
28
  def globals_load_as_hashes
24
- status = {status: 'pass', error: ''}
29
+ status = { status: 'pass', error: '' }
25
30
  non_hash_globals = []
26
31
  @globals.each do |path, loaded|
27
32
  if loaded.class != Hash
@@ -36,13 +41,13 @@ module PropertyGenerator
36
41
  end
37
42
 
38
43
  def globals_have_no_hashes_as_values
39
- status = {status: 'pass', error: ''}
44
+ status = { status: 'pass', error: '' }
40
45
  globals_with_hash_props = []
41
46
  @globals.each do |path, loaded|
42
47
  if loaded.class == Hash
43
48
  loaded.each do |key, value|
44
49
  if value.class == Hash
45
- globals_with_hash_props << {path => key}
50
+ globals_with_hash_props << { path => key }
46
51
  end
47
52
  end
48
53
  end
@@ -55,30 +60,30 @@ module PropertyGenerator
55
60
  end
56
61
 
57
62
  def globals_are_defined_for_valid_environemnts
58
- status = {status: 'pass', error: ''}
63
+ status = { status: 'pass', error: '' }
59
64
  ignore_list = ['globals.yml']
60
- globals_with_invalid_environments = []
61
- accounts = []
62
- if @configs['accounts'] != nil
63
- @configs['accounts'].each do |account|
64
- accounts << account.to_s
65
- end
66
- @globals.each do |path, loaded|
67
- unless @configs['environments'].include?((path.split('/')[(path.split('/')).length - 1]).split('.')[0]) || accounts.include?((path.split('/')[(path.split('/')).length - 1]).split('.')[0])
68
- globals_with_invalid_environments << path unless ignore_list.include?(path.split('/')[(path.split('/')).length - 1])
69
- end
70
- end
71
- if globals_with_invalid_environments != []
72
- status[:status] = 'warn'
73
- status[:error] = "Files #{globals_with_invalid_environments} do not have names matching a declared environment."
74
- end
75
- else
65
+
66
+ if @configs['accounts'].nil?
76
67
  status[:status] = 'warn'
77
- status[:error] = "Accounts list in config file is missing."
68
+ status[:error] = 'Accounts list in config file is missing.'
69
+ return status
70
+ end
71
+
72
+ accounts = @configs['accounts'].map(&:to_s)
73
+ globals_with_invalid_environments = @globals.keys.select do |path|
74
+ p = Pathname.new(path)
75
+ filename = p.basename(File.extname(path)).to_s
76
+ next if ignore_list.include?(p.basename.to_s)
77
+
78
+ !(@configs['environments'].include?(filename) || accounts.include?(filename))
78
79
  end
79
- status
80
- end
81
80
 
81
+ unless globals_with_invalid_environments.empty?
82
+ status[:status] = 'warn'
83
+ status[:error] = "Files #{globals_with_invalid_environments} do not have names matching a declared environment."
84
+ end
82
85
 
86
+ status
87
+ end
83
88
  end
84
89
  end
data/lib/linter/linter.rb CHANGED
@@ -1,17 +1,32 @@
1
1
  module PropertyGenerator
2
- require_relative 'config_linter.rb'
3
- require_relative 'globals_linter.rb'
4
- require_relative 'services_linter.rb'
5
- require_relative 'report.rb'
2
+ require_relative 'config_linter'
3
+ require_relative 'globals_linter'
4
+ require_relative 'services_linter'
5
+ require_relative 'report'
6
6
  class Linter
7
+ attr_accessor :ignored_tests, :services_linter, :globals_linter, :config_linter, :report
7
8
 
8
9
  def initialize(path)
9
- ignore_list = ['README.md']
10
+ ignore_list = %w[README.md .cpsignore]
10
11
  invalid_paths = PropertyGenerator.invalid_paths(path, ignore_list)
11
- @config_linter = PropertyGenerator::ConfigLinter.new(path+"/config/config.yml")
12
- @globals_linter = PropertyGenerator::GlobalsLinter.new(path+"/globals/", @config_linter.configs)
13
- @services_linter = PropertyGenerator::ServicesLinter.new(path+"/services/", @config_linter.configs)
14
- @report = PropertyGenerator::Report.new(invalid_paths)
12
+ begin
13
+ @ignored_tests = YAML.load_file("#{path}/.cpsignore")
14
+ rescue StandardError
15
+ @ignored_tests = {}
16
+ end
17
+ @config_linter = PropertyGenerator::ConfigLinter.new("#{path}/config/config.yml", @ignored_tests['config'] || [])
18
+ @globals_linter = PropertyGenerator::GlobalsLinter.new("#{path}/globals/", @config_linter.configs, @ignored_tests['globals'] || [])
19
+ @services_linter = PropertyGenerator::ServicesLinter.new("#{path}/services/", @config_linter.configs, @ignored_tests['services'] || [])
20
+
21
+ unless @ignored_tests['display_skipped_tests'].nil?
22
+ if @ignored_tests['display_skipped_tests']
23
+ @ignored_tests.delete('display_skipped_tests')
24
+ else
25
+ @ignored_tests = []
26
+ end
27
+ end
28
+
29
+ @report = PropertyGenerator::Report.new(invalid_paths, @ignored_tests)
15
30
  end
16
31
 
17
32
  def run_tests
@@ -34,6 +49,5 @@ module PropertyGenerator
34
49
  def display_report
35
50
  @report.display_report
36
51
  end
37
-
38
52
  end
39
53
  end
data/lib/linter/report.rb CHANGED
@@ -2,9 +2,10 @@ module PropertyGenerator
2
2
  require 'terminal-table'
3
3
 
4
4
  class Report
5
- def initialize(files_failing_load)
5
+ def initialize(files_failing_load, ignored_tests)
6
6
  @files_failing_load = files_failing_load
7
7
  @full_report = {}
8
+ @ignored_tests = ignored_tests
8
9
  end
9
10
 
10
11
  def add_report(report)
@@ -12,12 +13,16 @@ module PropertyGenerator
12
13
  end
13
14
 
14
15
  def display_report
15
- if @files_failing_load != []
16
- make_failing_to_load_table
16
+ unless @files_failing_load.empty?
17
+ puts make_failing_to_load_table
18
+ puts '*****************'
19
+ puts "Check for property values that start with an interpolated value \nIf the first character of the value is a bracket yaml will fail to load \nPlace the value in quotes"
20
+ puts '*****************'
17
21
  end
18
- make_pass_table
19
- make_warn_table
20
- make_fail_table
22
+ puts make_skip_table
23
+ puts make_pass_table
24
+ puts make_warn_table
25
+ puts make_fail_table
21
26
  end
22
27
 
23
28
  def has_a_test_failed
@@ -39,45 +44,43 @@ module PropertyGenerator
39
44
  @files_failing_load.each do |failed|
40
45
  rows << [failed]
41
46
  end
42
- table = Terminal::Table.new :headings => ['Files'], :title => 'Files Failing to Load', :rows => rows, :style => {:width => 200}
43
- puts table
44
- puts "*****************"
45
- puts "Check for property values that start with an interpolated value \nIf the first character of the value is a bracket yaml will fail to load \nPlace the value in quotes"
46
- puts "*****************"
47
+ Terminal::Table.new :headings => ['Files'], :title => 'Files Failing to Load', :rows => rows, :style => { :width => 200 }
48
+ end
49
+
50
+ def make_skip_table
51
+ return if @ignored_tests.empty?
52
+
53
+ Terminal::Table.new(headings: ['Test'], title: 'Skipped Tests', rows: @ignored_tests.values, style: { width: 200 })
47
54
  end
48
55
 
49
56
  def make_pass_table
50
57
  rows = []
51
- @full_report.each do |test,status|
58
+ @full_report.each do |test, status|
52
59
  if status[:status] == 'pass'
53
60
  rows << [test.gsub('_', ' ')]
54
61
  end
55
62
  end
56
- table = Terminal::Table.new :headings => ['Test'], :title => 'Passing Tests', :rows => rows, :style => {:width => 200}
57
- puts table
63
+ Terminal::Table.new(headings: ['Test'], title: 'Passing Tests', rows: rows, style: { width: 200 })
58
64
  end
59
65
 
60
66
  def make_warn_table
61
67
  rows = []
62
- @full_report.each do |test,status|
68
+ @full_report.each do |test, status|
63
69
  if status[:status] == 'warn'
64
70
  rows << [test.gsub('_', ' '), status[:error].scan(/.{1,90}/).join("\n")]
65
71
  end
66
72
  end
67
- table = Terminal::Table.new :headings => ['Test', 'Error'], :title => 'Warning Tests', :rows => rows, :style => {:width => 200}
68
- puts table
73
+ Terminal::Table.new(headings: ['Test', 'Error'], title: 'Warning Tests', rows: rows, style: { width: 200 })
69
74
  end
70
75
 
71
76
  def make_fail_table
72
77
  rows = []
73
- @full_report.each do |test,status|
78
+ @full_report.each do |test, status|
74
79
  if status[:status] == 'fail'
75
80
  rows << [test.gsub('_', ' '), status[:error].scan(/.{1,90}/).join("\n")]
76
81
  end
77
82
  end
78
- table = Terminal::Table.new :headings => ['Test', 'Error'], :title => 'Failing Tests', :rows => rows, :style => {:width => 200}
79
- puts table
83
+ Terminal::Table.new(headings: ['Test', 'Error'], title: 'Failing Tests', rows: rows, style: { width: 200 })
80
84
  end
81
-
82
85
  end
83
86
  end
@@ -2,10 +2,19 @@ require_relative '../helpers/helpers'
2
2
  module PropertyGenerator
3
3
  require 'yaml'
4
4
  class ServicesLinter
5
+ TESTS = [
6
+ 'services_have_accepted_keys',
7
+ 'service_environments_are_not_empty',
8
+ 'service_environments_match_config_environments',
9
+ 'service_encrypted_environments_match_config_environments',
10
+ 'service_encrypted_fields_are_correct',
11
+ 'service_encrypted_region_field_is_accepted'
12
+ ].freeze
5
13
 
6
- def initialize(path, configs)
14
+ def initialize(path, configs, ignored_tests)
7
15
  @configs = configs
8
16
  @services = {}
17
+ @ignored_tests = ignored_tests
9
18
  valid_paths = PropertyGenerator.valid_paths(path)
10
19
  valid_paths.each do |file_path|
11
20
  @services[file_path] = YAML.load_file(file_path)
@@ -13,28 +22,19 @@ module PropertyGenerator
13
22
  end
14
23
 
15
24
  def run_services_tests
16
- tests = [
17
- 'services_have_accepted_keys',
18
- 'service_environments_are_not_empty',
19
- 'service_defaults_have_no_hashes_as_values',
20
- 'service_environments_match_config_environments',
21
- 'service_environments_have_no_hashes_as_values',
22
- 'service_encrypted_environments_match_config_environments',
23
- 'service_encrypted_fields_are_correct',
24
- 'service_encrypted_region_field_is_accepted'
25
- ]
26
- results = PropertyGenerator.test_runner(self, tests)
27
- results
25
+ tests = TESTS - @ignored_tests
26
+
27
+ PropertyGenerator.test_runner(self, tests)
28
28
  end
29
29
 
30
30
  def service_environments_are_not_empty
31
- status = {status: 'pass', error: ''}
31
+ status = { status: 'pass', error: '' }
32
32
  services_empty_environments = []
33
33
  @services.each do |path, loaded|
34
- unless loaded['environments'] == nil
34
+ unless loaded['environments'].nil?
35
35
  loaded['environments'].each do |environments, properties|
36
- if properties == nil
37
- services_empty_environments << {path => environments}
36
+ if properties.nil?
37
+ services_empty_environments << { path => environments }
38
38
  end
39
39
  end
40
40
  end
@@ -47,13 +47,13 @@ module PropertyGenerator
47
47
  end
48
48
 
49
49
  def services_have_accepted_keys
50
- status = {status: 'pass', error: ''}
50
+ status = { status: 'pass', error: '' }
51
51
  accepted_keys = ['default', 'environments', 'encrypted', 'configname', 'stringdata', 'configlabels', 'secretlabels', 'label']
52
52
  services_with_unacceptable_keys = []
53
53
  @services.each do |path, loaded|
54
54
  loaded.keys.each do |service_key|
55
55
  unless accepted_keys.include?(service_key)
56
- services_with_unacceptable_keys << {path => service_key}
56
+ services_with_unacceptable_keys << { path => service_key }
57
57
  end
58
58
  end
59
59
  end
@@ -64,38 +64,19 @@ module PropertyGenerator
64
64
  status
65
65
  end
66
66
 
67
- def service_defaults_have_no_hashes_as_values
68
- status = {status: 'pass', error: ''}
69
- services_with_hashes_in_defaults = []
70
- @services.each do |path, loaded|
71
- unless loaded['default'] == nil
72
- loaded['default'].each do |defaultkey, defaultvalue|
73
- if defaultvalue.class == Hash
74
- services_with_hashes_in_defaults << {path => defaultkey}
75
- end
76
- end
77
- end
78
- end
79
- if services_with_hashes_in_defaults != []
80
- status[:status] = 'fail'
81
- status[:error] = "Service files: #{services_with_hashes_in_defaults} have default properties with values as hashes."
82
- end
83
- status
84
- end
85
-
86
67
  def service_environments_match_config_environments
87
- status = {status: 'pass', error: ''}
68
+ status = { status: 'pass', error: '' }
88
69
  missmatched_environments = []
89
70
  @services.each do |path, loaded|
90
- if loaded['environments'] != nil
91
- loaded['environments'].keys.each do |environment|
92
- if @configs['environments'] != nil
93
- unless @configs['environments'].include?(environment)
94
- missmatched_environments << {path => environment}
95
- end
96
- else
97
- status[:status] = 'warn'
98
- status[:error] = "Environments list in config file is missing."
71
+ next if loaded['environments'].nil?
72
+
73
+ loaded['environments'].keys.each do |environment|
74
+ if @configs['environments'].nil?
75
+ status[:status] = 'warn'
76
+ status[:error] = 'Environments list in config file is missing.'
77
+ else
78
+ unless @configs['environments'].include?(environment)
79
+ missmatched_environments << { path => environment }
99
80
  end
100
81
  end
101
82
  end
@@ -107,42 +88,19 @@ module PropertyGenerator
107
88
  status
108
89
  end
109
90
 
110
- def service_environments_have_no_hashes_as_values
111
- status = {status: 'pass', error: ''}
112
- services_with_hashes_in_environments = []
113
- @services.each do |path, loaded|
114
- unless loaded['environments'] == nil
115
- loaded['environments'].each do |environments, properties|
116
- unless properties == nil
117
- properties.each do |key, value|
118
- if value.class == Hash
119
- services_with_hashes_in_environments << {path => {environments => key}}
120
- end
121
- end
122
- end
123
- end
124
- end
125
- end
126
- if services_with_hashes_in_environments != []
127
- status[:status] = 'fail'
128
- status[:error] = "Service files #{services_with_hashes_in_environments} have environment properties with values as hashes."
129
- end
130
- status
131
- end
132
-
133
91
  def service_encrypted_environments_match_config_environments
134
- status = {status: 'pass', error: ''}
92
+ status = { status: 'pass', error: '' }
135
93
  missmatched_environments = []
136
94
  @services.each do |path, loaded|
137
- if loaded['encrypted'] != nil
138
- loaded['encrypted'].keys.each do |environment|
139
- if @configs['environments'] != nil
140
- unless @configs['environments'].include?(environment)
141
- missmatched_environments << {path => environment}
142
- end
143
- else
144
- status[:status] = 'warn'
145
- status[:error] = "Environments list in config file is missing."
95
+ next if loaded['encrypted'].nil?
96
+
97
+ loaded['encrypted'].keys.each do |environment|
98
+ if @configs['environments'].nil?
99
+ status[:status] = 'warn'
100
+ status[:error] = 'Environments list in config file is missing.'
101
+ else
102
+ unless @configs['environments'].include?(environment)
103
+ missmatched_environments << { path => environment }
146
104
  end
147
105
  end
148
106
  end
@@ -154,66 +112,103 @@ module PropertyGenerator
154
112
  status
155
113
  end
156
114
 
115
+ def recursive_find_keys(obj, key)
116
+ if obj.respond_to?(:key?) && obj.key?(key)
117
+ obj[key]
118
+ elsif obj.is_a?(Hash) or obj.is_a?(Array)
119
+ r = nil
120
+ obj.find{ |*a| r = recursive_find_keys(a.last,key) }
121
+ r
122
+ end
123
+ end
124
+
157
125
  def service_encrypted_fields_are_correct
158
- status = {status: 'pass', error: ''}
126
+ status = { status: 'pass', error: '' }
159
127
  accepted_keys = ['region', 'encrypted', 'service', 'label']
160
128
  services_with_unacceptable_keys = []
161
129
  @services.each do |path, loaded|
162
- if loaded['encrypted'] != nil
163
- loaded['encrypted'].each do |environment, properties|
164
- properties.each do |property, value|
165
- if value == nil
166
- services_with_unacceptable_keys << {path => {environment => property}}
167
- elsif value['$ssm'] == nil
168
- services_with_unacceptable_keys << {path => {environment => property}}
169
- else
170
- if value['$ssm'] != nil
171
- value['$ssm'].keys.each do |key|
172
- unless accepted_keys.include?(key)
173
- services_with_unacceptable_keys << {path => {environment => property}}
174
- end
175
- end
130
+ next if loaded['encrypted'].nil?
131
+
132
+ loaded['encrypted'].each do |environment, properties|
133
+ properties.each do |property, value|
134
+ if value.nil?
135
+ services_with_unacceptable_keys << { path => { environment => property } }
136
+ next
137
+ end
138
+
139
+ s = recursive_find_keys(value, '$ssm')
140
+ k = recursive_find_keys(value, '$kms')
141
+ if s.nil? && k.nil?
142
+ services_with_unacceptable_keys << { path => { environment => property } }
143
+ next
144
+ end
145
+
146
+ unless s.nil?
147
+ s.keys.each do |key|
148
+ unless accepted_keys.include?(key)
149
+ services_with_unacceptable_keys << { path => { environment => property } }
150
+ next
176
151
  end
177
152
  end
178
153
  end
154
+
155
+ unless k.nil?
156
+ if (k.keys & ['region', 'encrypted']).count != 2
157
+ services_with_unacceptable_keys << { path => { environment => property } }
158
+ end
159
+ end
179
160
  end
180
161
  end
181
162
  end
182
- if services_with_unacceptable_keys != []
163
+ unless services_with_unacceptable_keys.empty?
183
164
  status[:status] = 'fail'
184
- status[:error] = "Service files: #{services_with_unacceptable_keys} have encrypted properties with bad indentation or keys other than 'region', 'encrypted' or 'label'."
165
+ status[:error] = "Service files: #{services_with_unacceptable_keys} has an encrypted block without " +
166
+ "properties, encrypted properties without $kms or $ssm blocks, or encrypted blocks with either bad " +
167
+ "indentation or incorrect keys."
185
168
  end
186
169
  status
187
170
  end
188
171
 
189
172
  def service_encrypted_region_field_is_accepted
190
- status = {status: 'pass', error: ''}
173
+ status = { status: 'pass', error: '' }
191
174
  services_with_unacceptable_keys = []
192
175
  @services.each do |path, loaded|
193
- if loaded['encrypted'] != nil
194
- loaded['encrypted'].each do |environment, property|
195
- if loaded['encrypted'][environment][property] != nil
196
- loaded['encrypted'][environment][property].each do |ssm, keys|
197
- if @configs['environments'] != nil
198
- unless @configs['environments'].include?(loaded['encrypted'][environment][property]['$ssm'][keys]['region'])
199
- services_with_unacceptable_keys << {path => {environment => property}}
200
- end
201
- else
202
- status[:status] = 'warn'
203
- status[:error] = "Environments list in config file is missing."
204
- end
176
+ next if loaded['encrypted'].nil?
177
+
178
+ loaded['encrypted'].each do |environment, properties|
179
+ if loaded['encrypted'][environment].nil?
180
+ status[:status] = 'error'
181
+ status[:error] = 'Encrypted properties are missing from the encrypted environment'
182
+ return status
183
+ end
184
+
185
+ encrypted_env = loaded['encrypted'][environment]
186
+
187
+ # next if encrypted_env[property].nil?
188
+
189
+ encrypted_env.each do |property, encrypted_values|
190
+ if @configs['environments'].nil?
191
+ status[:status] = 'warn'
192
+ status[:error] = 'Environments list in config file is missing.'
193
+ break
194
+ end
195
+
196
+ %w[$ssm $kms].each do |encryption_type|
197
+ values = recursive_find_keys(encrypted_values, encryption_type)
198
+ next if values.nil?
199
+
200
+ unless @configs['environments'].include?(values['region'])
201
+ services_with_unacceptable_keys << { path => { environment => property } }
205
202
  end
206
203
  end
207
204
  end
208
205
  end
209
206
  end
210
- if services_with_unacceptable_keys != []
207
+ if !services_with_unacceptable_keys.empty? && status[:status] == 'pass'
211
208
  status[:status] = 'warn'
212
209
  status[:error] = "Service files: #{services_with_unacceptable_keys} have encrypted properties a region field not matching a declared environment in the configs."
213
210
  end
214
211
  status
215
212
  end
216
-
217
-
218
213
  end
219
214
  end