opensecret 0.0.2 → 0.0.4

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/README.md +2 -2
  4. data/bin/opensecret +3 -6
  5. data/lib/opensecret-domain.ini +23 -0
  6. data/lib/opensecret.rb +30 -2
  7. data/lib/opensecret/additions/array.rb +117 -0
  8. data/lib/opensecret/additions/dir.rb +35 -0
  9. data/lib/opensecret/additions/string.rb +312 -0
  10. data/lib/opensecret/commons/eco.cmdline.rb +446 -0
  11. data/lib/opensecret/commons/eco.faculty.rb +364 -0
  12. data/lib/opensecret/commons/eco.system.rb +437 -0
  13. data/lib/opensecret/commons/eco.systems.rb +98 -0
  14. data/lib/opensecret/{safe.rb → delegate.rb} +4 -2
  15. data/lib/opensecret/eco.do.rb +46 -0
  16. data/lib/opensecret/executors/crypt.keys/crypt.keys.ini +79 -0
  17. data/lib/opensecret/executors/crypt.keys/crypt.keys.rb +68 -0
  18. data/lib/opensecret/executors/decrypt/decrypt.ini +64 -0
  19. data/lib/opensecret/executors/decrypt/decrypt.rb +49 -0
  20. data/lib/opensecret/executors/encrypt/encrypt.ini +55 -0
  21. data/lib/opensecret/executors/encrypt/encrypt.rb +82 -0
  22. data/lib/opensecret/factbase/hub-runtime.ini +123 -0
  23. data/lib/opensecret/factbase/known-hosts.ini +75 -0
  24. data/lib/opensecret/factbase/published.facts/blobbolicious-facts.ini +553 -0
  25. data/lib/opensecret/factbase/published.facts/credential-facts.ini +40 -0
  26. data/lib/opensecret/factbase/published.facts/infrastructure-facts.ini +63 -0
  27. data/lib/opensecret/factbase/readme.md +24 -0
  28. data/lib/opensecret/factbase/retired.facts/maven.database.ide.facts.ini +127 -0
  29. data/lib/opensecret/factbase/retired.facts/s3-upload-block-facts.ini +17 -0
  30. data/lib/opensecret/plugins.io/cipher/crypto.rb +174 -0
  31. data/lib/opensecret/plugins.io/error/eco.exceptions.rb +24 -0
  32. data/lib/opensecret/plugins.io/facts/fact.chars.rb +66 -0
  33. data/lib/opensecret/plugins.io/facts/fact.factor.rb +156 -0
  34. data/lib/opensecret/plugins.io/facts/fact.locator.rb +105 -0
  35. data/lib/opensecret/plugins.io/facts/fact.reader.rb +137 -0
  36. data/lib/opensecret/plugins.io/facts/fact.tree.rb +661 -0
  37. data/lib/opensecret/plugins.io/file/file.rb +483 -0
  38. data/lib/opensecret/plugins.io/git/git.flow.rb +388 -0
  39. data/lib/opensecret/plugins.io/logs/log.object.rb +89 -0
  40. data/lib/opensecret/plugins.io/logs/logging.rb +203 -0
  41. data/lib/opensecret/plugins.io/time/time.stamp.rb +425 -0
  42. data/lib/opensecret/version.rb +2 -2
  43. data/opensecret.gemspec +8 -13
  44. metadata +68 -18
@@ -0,0 +1,483 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # -- --------------------------------------------------------------- -- #
4
+ # -- File facts are placeholders (keys in effect) just begging to be -- #
5
+ # -- replaced by values sourced from some sort of map. This software -- #
6
+ # -- centres around the DevOps fact replacement placeholder pattern. -- #
7
+ # -- --------------------------------------------------------------- -- #
8
+ class Files
9
+ #### ==> ===================================================================================
10
+ #### ==> ===================================================================================
11
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
12
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
13
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
14
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
15
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
16
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
17
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
18
+ #### ==> ===================================================================================
19
+ #### ==> ===================================================================================
20
+
21
+
22
+
23
+ ## --- ---------------------------------------------------------------------- --- #
24
+ ## --- How to Use File to extract different parts of an [absolute] file path. --- #
25
+ ## --- ---------------------------------------------------------------------- --- #
26
+ ### File Names ====] file = "/path/to/xyz.mp4"
27
+ ### File Names ====] comp = File.basename file # => "xyz.mp4"
28
+ ### File Names ====] extn = File.extname file # => ".mp4"
29
+ ### File Names ====] name = File.basename file, extn # => "xyz"
30
+ ### File Names ====] path = File.dirname file # => "/path/to"
31
+ ## --- ---------------------------------------------------------------------- --- #
32
+
33
+
34
+ # --
35
+ # -- Scan every file in directory for placeholder keys within the
36
+ # -- parameter map and replace them with the corresponding value.
37
+ # -- Not Recursive => the scan does [not] recurse into folders
38
+ # --
39
+ # -- ----------------------------------
40
+ # -- Replacing Betty (Nested Replace)
41
+ # -- ----------------------------------
42
+ # --
43
+ # -- "GoBBetBettytyettyne" => "Gone"
44
+ # --
45
+ # -- A nested replace is done up to approximately 5 levels deep.
46
+ # -- So replacing "Betty" from the above string does [NOT] produce
47
+ # -- "GoBBettyettyne". The string becomes "Gone".
48
+ # --
49
+ # -- -----------
50
+ # -- Parameters
51
+ # -- -----------
52
+ # -- fact_map : driving [placeholder] => [value] map
53
+ # -- replace_dir : dir subject of the scan and replace
54
+ # --
55
+ def self.find_replace fact_map, replace_folder
56
+
57
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
58
+ log.info(ere){ "#-- File changing in #{File.basename replace_folder}" }
59
+ log.info(ere){ "#-- #{replace_folder}" }
60
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
61
+
62
+ # -- ------------------------------------------------------------------------------ -- #
63
+ # -- Iterate to substitute matched strings in file with their corresponding values. -- #
64
+ # -- ------------------------------------------------------------------------------ -- #
65
+ Dir.foreach( replace_folder ) do | file_name |
66
+
67
+ file_path = File.join replace_folder, file_name
68
+ next if File.directory? file_path
69
+ next if File.extname(file_path).eql? ".log"
70
+
71
+ nested_key_replace fact_map, file_path
72
+
73
+ end
74
+
75
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
76
+ log.info(ere){ "#-- Done changing files in #{File.basename replace_folder}" }
77
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
78
+
79
+ end
80
+
81
+ #--
82
+ #-- Using the parameter [file] [replace] any occurence
83
+ #-- of any [key] found in the parameter [map] with the
84
+ #-- corresponding mapped key [value].
85
+ #--
86
+ #-- -----------------------------------
87
+ #-- [Nested Replace]
88
+ # -- Replacing Betty (Nested Replace)
89
+ # -- ----------------------------------
90
+ # --
91
+ # -- "GoBBetBettytyettyne" => "Gone"
92
+ # --
93
+ # -- A nested replace is done up to approximately 5 levels deep.
94
+ # -- So replacing "Betty" from the above string does [NOT] produce
95
+ # -- "GoBBettyettyne". The string becomes "Gone".
96
+ # --
97
+ def self.nested_key_replace source_map, filepath
98
+
99
+ for i in 1..5
100
+ file_changed = key_replace source_map, filepath
101
+ return unless file_changed
102
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
103
+ log.info(ere){ "#-- File #{File.basename filepath} has been changed" }
104
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
105
+ end
106
+
107
+ end
108
+
109
+ #--
110
+ #-- Using the parameter [file] [replace] any occurence
111
+ #-- of any [key] found in the parameter [map] with the
112
+ #-- corresponding mapped key [value].
113
+ #--
114
+ #-- Side Effect => If at least one replacement occured this
115
+ #-- method returns true, else false.
116
+ #--
117
+ def self.key_replace source_map, filepath
118
+
119
+ replace_happened = false
120
+
121
+ source_map.each do |theKey, theValue|
122
+
123
+ next unless has_string? filepath, theKey
124
+ factorize theKey, theValue, filepath
125
+ replace_happened = true
126
+
127
+ end
128
+
129
+ return replace_happened
130
+
131
+ end
132
+
133
+
134
+
135
+ #--
136
+ #-- Produce a map of every "recursive" file sitting under
137
+ #-- any and all of the parameter directories array.
138
+ #--
139
+ #-- Harboured folders are traversed but folder names are
140
+ #-- excluded from the resulting map.
141
+ #--
142
+ #-- The key/value structure of the map is
143
+ #--
144
+ #-- key => simple filename
145
+ #-- value => (abs) folder path
146
+ #--
147
+ #-- --------------------------------
148
+ #-- Filename NOT UNIQUE Exception
149
+ #-- --------------------------------
150
+ #--
151
+ #-- Simple filename UNIQUENESS must prevail.
152
+ #--
153
+ #-- If the same base filename is found in any part or level
154
+ #-- of the directory trees under the every parameter parent
155
+ #-- folder - an exception will be thrown.
156
+ #--
157
+ def self.in_folders parent_folders
158
+
159
+ files_map = {}
160
+
161
+ parent_folders.each do |parent_folder|
162
+
163
+ log.info(ere) { "Create map of files under #{nickname parent_folder}" }
164
+ Throw.if_not_exists parent_folder
165
+
166
+ Dir["#{parent_folder}/**/*"].each do |child_file|
167
+
168
+ next if File.directory? child_file
169
+ filename = File.basename child_file
170
+ foldername = File.dirname child_file
171
+ log.info(ere) { " #{filename} => #{nickname foldername}" }
172
+ error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
173
+ raise RuntimeError.new error_str if files_map.has_key? filename
174
+ files_map.store filename, foldername
175
+
176
+ end
177
+
178
+ end
179
+
180
+ return files_map
181
+
182
+ end
183
+
184
+
185
+ #--
186
+ #-- Find files of a given type (extension) that exist
187
+ #-- recursively under a folder.
188
+ #--
189
+ #-- --------------------------------
190
+ #-- Filename NOT UNIQUE Exception
191
+ #-- --------------------------------
192
+ #--
193
+ #-- Simple filename UNIQUENESS must prevail.
194
+ #--
195
+ #-- If the same base filename is found in any part or level
196
+ #-- of the directory trees under the every parameter parent
197
+ #-- folder - an exception will be thrown.
198
+ #--
199
+ #-- ------------
200
+ #-- Parameters
201
+ #-- ------------
202
+ #--
203
+ #-- base_folder => the top-level folder to search
204
+ #-- dir at (abs) path must exist
205
+ #--
206
+ #-- file_extn => extension of interesting files
207
+ #-- including the leading [period].
208
+ #-- (send ".exe" for exe files)
209
+ #-- (send ".md" for markdown files)
210
+ #--
211
+ #-- ------------
212
+ #-- Map Returned
213
+ #-- ------------
214
+ #--
215
+ #-- Returns a { filename => rel_path } map of the matching
216
+ #-- files in the folder. The map
217
+ #--
218
+ #-- keys => simple filename without extension
219
+ #-- values => relative path from the base folder
220
+ #--
221
+ def self.to_name_path_map base_folder, file_extn
222
+
223
+ files_map = {}
224
+
225
+ Dir["#{base_folder}/**/*#{file_extn}"].each do |filepath|
226
+
227
+ next if File.directory? filepath
228
+ ext_error = "File extension not [#{file_extn}] in => #{nickname filepath}"
229
+ raise RuntimeError.new(ext_error) unless File.extname(filepath).eql? "#{file_extn}"
230
+
231
+ filename = File.basename filepath
232
+
233
+ error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
234
+ raise RuntimeError.new error_str if files_map.has_key? filename
235
+ files_map.store filename, filepath
236
+
237
+ end
238
+
239
+ return files_map
240
+
241
+ end
242
+
243
+
244
+ #--
245
+ #-- Return a new map with the values folder path
246
+ #-- forwarded by one level
247
+ #--
248
+ #-- If the map contains the below
249
+ #--
250
+ #-- {
251
+ #-- file1 => user/docs/pdfs,
252
+ #-- file2 => user/docs/pdfs/good,
253
+ #-- file3 => user/docs/pdfs/bad
254
+ #-- }
255
+ #--
256
+ #-- This method will return a map like this
257
+ #--
258
+ #-- {
259
+ #-- file1 => docs/pdfs,
260
+ #-- file2 => docs/pdfs/good,
261
+ #-- file3 => docs/pdfs/bad
262
+ #-- }
263
+ #--
264
+ #-- The values part has been forwarded by one level.
265
+ #--
266
+ def self.forwarded_path files_map
267
+
268
+ changed_map = {}
269
+
270
+ files_map.each do |the_name, the_old_path|
271
+ the_new_path = the_old_path.split("/")[1..-1].join("/")
272
+ changed_map.store the_name, the_new_path
273
+ log.info(ere){ "Forwarded from #{the_old_path} to #{the_new_path}" }
274
+ end
275
+
276
+ return changed_map
277
+
278
+ end
279
+
280
+
281
+ #--
282
+ #-- Path stripper expects the path in the first parameter
283
+ #-- to start with the path in the second parameter.
284
+ #--
285
+ #-- It then returns the first parameter path with the
286
+ #-- leading path stripped out.
287
+ #--
288
+ #-- ---------------------------
289
+ #-- Strip Leading Path Example
290
+ #-- ---------------------------
291
+ #--
292
+ #-- 1st param path = /home/joe/docs/pdfs/websites
293
+ #-- 2nd param path = /home/joe/docs
294
+ #-- Returned Path = pdfs/websites
295
+ #--
296
+ #-- ---------------------------------
297
+ #-- The Middle Separator is Stripped
298
+ #-- ---------------------------------
299
+ #--
300
+ #-- Note above that the middle separator is stripped
301
+ #-- so the returned string has no leading separator.
302
+ #--
303
+ def self.lead_path_chopped long_path, lead_path
304
+
305
+ return long_path.gsub(lead_path, "")[1..-1]
306
+
307
+ end
308
+
309
+
310
+ # -- ------------------------------------------------------------------- -- #
311
+ # -- Returns true when the parameter file contains the parameter string. -- #
312
+ # -- As a side effect the lines with at least 1 string match are logged. -- #
313
+ # -- ------------------------------------------------------------------- -- #
314
+ def self.has_string? the_file, theString
315
+
316
+ containsMatch = false;
317
+ line_index = 0;
318
+
319
+ File.open( the_file, "r") do | file_obj |
320
+
321
+ name_abbrv = File.basename the_file
322
+ file_obj.each_line do | file_line |
323
+
324
+ line_index = line_index + 1
325
+ lineCount = sprintf '%03d', line_index
326
+ if file_line.include? theString then
327
+
328
+ squeezed_line = file_line.chomp.strip.squeeze(" ")
329
+ log.info(ere) { "== string [#{theString}] occurs @line #{lineCount} in #{name_abbrv}" }
330
+ log.info(ere) { "== |---> #{squeezed_line}" }
331
+ containsMatch = true
332
+
333
+ end
334
+
335
+ end
336
+
337
+ end
338
+
339
+ return containsMatch;
340
+
341
+ end
342
+
343
+
344
+ # --
345
+ # -- [FIND] lines that include a set of configured strings and
346
+ # -- [REPLACE] then with the configured alternative.
347
+ # --
348
+ # -- -----------
349
+ # -- Parameters
350
+ # -- -----------
351
+ # --
352
+ # -- filepath : path to existing "to be changed" file
353
+ # -- includes : include string array for line matching
354
+ # -- new_line : replace the matched line with this str
355
+ # --
356
+ # -- --------------------------------
357
+ # -- Dependencies and Assumptions
358
+ # -- --------------------------------
359
+ # --
360
+ # -- file exists at filepath
361
+ # --
362
+ def self.find_replace_lines filepath, includes, new_line
363
+
364
+ Throw.if_not_exists filepath
365
+ Throw.if_nil includes
366
+ Throw.if_nil new_line
367
+
368
+ line_matches_count = 0;
369
+ new_file_lines_set = ""
370
+
371
+ File.open( filepath, "r") do | file_obj |
372
+
373
+ file_obj.each_line do | file_line |
374
+
375
+ unless (String.includes_all?( file_line, includes ) ) then
376
+ new_file_lines_set += file_line
377
+ next
378
+ end
379
+
380
+ ++line_matches_count
381
+ new_file_lines_set += new_line
382
+
383
+ log.info(ere) { "[replace] - ------------------------------------------------------- ##" }
384
+ log.info(ere) { "[replace] - file name => #{File.basename filepath}" }
385
+ log.info(ere) { "[replace] - has words => #{pp includes}" }
386
+ log.info(ere) { "[replace] - orig line => #{file_line}" }
387
+ log.info(ere) { "[replace] - ------- --------- ------- ---------- ------ ##" }
388
+ log.info(ere) { "[replace] - outgoing line => #{file_line}" }
389
+ log.info(ere) { "[replace] - incoming line => #{new_line}" }
390
+ log.info(ere) { "[replace] - ------- --------- ------- ---------- ------ ##" }
391
+
392
+ end
393
+
394
+ end
395
+
396
+ # -- ---------------------------------------------------------- -- #
397
+ # -- [(over)write] new set of file lines to the parameter file. -- #
398
+ # -- ---------------------------------------------------------- -- #
399
+ File.write filepath, new_file_lines_set
400
+ LogObject.file filepath, "replace"
401
+
402
+ end
403
+
404
+
405
+ # --
406
+ # -- Write the 1D key/value map into a properties
407
+ # -- file at the parameter folder.
408
+ # --
409
+ # -- Parameters
410
+ # -- properties_map : the key/value map to serialize
411
+ # -- props_dir_path : folder holding new properties file
412
+ # -- props_filename : name of the new properties file
413
+ # --
414
+ # -- Dependencies and Assumptions
415
+ # -- the directory will be created if it does not exist
416
+ # -- we assume the properties file DOES NOT EXIST
417
+ # -- the map is 1D and is not nil (can be empty)
418
+ # -- the directory is writeable by the user
419
+ # --
420
+ def self.write_properties properties_map, props_dir_path, props_filename
421
+
422
+ Dir.mkdir props_dir_path unless File.exists? props_dir_path
423
+ prop_filepath = File.join props_dir_path, props_filename
424
+ File.write prop_filepath, to_properties_text(properties_map)
425
+
426
+ LogObject.file prop_filepath, "write properties"
427
+
428
+ end
429
+
430
+
431
+ # --
432
+ # -- Create txt file in the properties format containing
433
+ # -- a dictionary of name/value pairs separated by an
434
+ # -- equals sign.
435
+ # --
436
+ # -- Parameters
437
+ # -- properties_map : the key/value map to serialize
438
+ # --
439
+ # -- Dependencies and Assumptions
440
+ # -- the map is 1D and is not nil (can be empty)
441
+ # -- map keys are SYMBOLS so underscores are made dots
442
+ # --
443
+ def self.to_properties_text properties_map
444
+
445
+ hdr_1 = "## Properties file with [#{properties_map.length}] key/value pairs.\n"
446
+ hdr_u = "## @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ##\n"
447
+
448
+ property_text = hdr_u + hdr_1 + hdr_u + "\n"
449
+ properties_map.each do |key_symbol,value|
450
+ key_string = key_symbol.to_s.gsub("_", ".")
451
+ property_text += "#{key_string}=#{value}\n"
452
+ end
453
+
454
+ property_text += "\n" + hdr_u
455
+ return property_text
456
+
457
+ end
458
+
459
+
460
+ # -- ---------------------------------------------------------- -- #
461
+ # -- When the [file fact] replace [behaviour] is called against -- #
462
+ # -- a "file" it [replaces all occurrences] (as best it can) of -- #
463
+ # -- the given string within the file. Call replace occurrences -- #
464
+ # -- against a folder and it replaces in all constituent files. -- #
465
+ # -- ---------------------------------------------------------- -- #
466
+ # -- Be careful = this implementation is not that clever. So if -- #
467
+ # -- we try to replace all "Betty" occurrences - lines that may -- #
468
+ # -- contain ["BetBettyty"] will likely end up with a ["Betty"] -- #
469
+ # -- ---------------------------------------------------------- -- #
470
+ def self.factorize from_string, to_string, in_file
471
+
472
+ the_filename = File.basename in_file
473
+
474
+ log.info(ere) { "From String => #{from_string}" }
475
+ log.info(ere) { "[To] String => #{to_string}" }
476
+ log.info(ere) { "File [Name] => #{the_filename}" }
477
+
478
+ File.write( in_file, File.open( in_file, &:read ).gsub( from_string, to_string ) );
479
+
480
+ end
481
+
482
+
483
+ end