opensecret 0.0.9925 → 0.0.9949
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/README.md +656 -40
- data/lib/configs/README.md +58 -0
- data/lib/extension/file.rb +67 -0
- data/lib/extension/string.rb +10 -0
- data/lib/factbase/facts.opensecret.io.ini +1 -0
- data/lib/interprete.rb +334 -61
- data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
- data/lib/keytools/kdf.api.rb +9 -15
- data/lib/keytools/kdf.bcrypt.rb +69 -19
- data/lib/keytools/kdf.pbkdf2.rb +112 -23
- data/lib/keytools/key.api.rb +146 -36
- data/lib/keytools/key.db.rb +94 -29
- data/lib/keytools/key.id.rb +1 -1
- data/lib/keytools/key.ident.rb +243 -0
- data/lib/keytools/key.local.rb +62 -68
- data/lib/keytools/key.pass.rb +2 -2
- data/lib/keytools/key.rb +2 -28
- data/lib/modules/{cryptology.md → README.md} +0 -0
- data/lib/session/fact.finder.rb +65 -428
- data/lib/session/time.stamp.rb +1 -28
- data/lib/usecase/cmd.rb +127 -54
- data/lib/usecase/config/README.md +57 -0
- data/lib/usecase/docker/README.md +146 -0
- data/lib/usecase/docker/docker.rb +49 -0
- data/lib/usecase/edit/README.md +43 -0
- data/lib/usecase/edit/delete.rb +46 -0
- data/lib/usecase/export.rb +40 -0
- data/lib/usecase/files/README.md +37 -0
- data/lib/usecase/files/eject.rb +56 -0
- data/lib/usecase/files/file_me.rb +78 -0
- data/lib/usecase/files/read.rb +169 -0
- data/lib/usecase/files/write.rb +89 -0
- data/lib/usecase/goto.rb +57 -0
- data/lib/usecase/id.rb +1 -1
- data/lib/usecase/import.rb +13 -30
- data/lib/usecase/init.rb +2 -17
- data/lib/usecase/jenkins/README.md +146 -0
- data/lib/usecase/jenkins/crazy_ruby_post_attempt.OLD +234 -0
- data/lib/usecase/jenkins/jenkins.rb +208 -0
- data/lib/usecase/login.rb +6 -5
- data/lib/usecase/logout.rb +1 -3
- data/lib/usecase/open.rb +11 -66
- data/lib/usecase/print.rb +40 -0
- data/lib/usecase/put.rb +34 -156
- data/lib/usecase/set.rb +2 -4
- data/lib/usecase/show.rb +138 -0
- data/lib/usecase/terraform/README.md +91 -0
- data/lib/usecase/terraform/terraform.rb +121 -0
- data/lib/usecase/token.rb +4 -80
- data/lib/usecase/update/README.md +55 -0
- data/lib/usecase/update/rename.rb +180 -0
- data/lib/usecase/use.rb +1 -3
- data/lib/usecase/verse.rb +20 -0
- data/lib/usecase/view.rb +71 -0
- data/lib/usecase/vpn/README.md +150 -0
- data/lib/usecase/vpn/vpn.ini +31 -0
- data/lib/usecase/vpn/vpn.rb +54 -0
- data/lib/version.rb +1 -1
- data/opensecret.gemspec +3 -4
- metadata +34 -35
- data/.travis.yml +0 -5
- data/CODE_OF_CONDUCT.md +0 -74
- data/LICENSE.txt +0 -21
- data/bin/ops +0 -20
- data/lib/keytools/binary.map.rb +0 -294
- data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +0 -179
- data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +0 -190
- data/lib/keytools/doc.star.schema.strategy.txt +0 -77
- data/lib/keytools/doc.using.pbkdf2.kdf.ruby +0 -95
- data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +0 -266
- data/lib/keytools/key.mach.rb +0 -248
- data/lib/keytools/keydebug.txt +0 -295
- data/lib/modules/cryptology/open.bcrypt.rb +0 -170
- data/lib/usecase/read.rb +0 -89
- data/lib/usecase/safe.rb +0 -92
data/lib/keytools/key.pass.rb
CHANGED
@@ -43,14 +43,14 @@ module OpenKey
|
|
43
43
|
assert_min_size MINIMUM_PASSWORD_SIZE
|
44
44
|
|
45
45
|
sleep(1)
|
46
|
-
puts "
|
46
|
+
puts "Password:"
|
47
47
|
first_secret = STDIN.noecho(&:gets).chomp
|
48
48
|
|
49
49
|
assert_input_text_size first_secret.length, MINIMUM_PASSWORD_SIZE
|
50
50
|
return first_secret unless prompt_twice
|
51
51
|
|
52
52
|
sleep(1)
|
53
|
-
puts "
|
53
|
+
puts "Re-enter the password:"
|
54
54
|
check_secret = STDIN.noecho(&:gets).chomp
|
55
55
|
|
56
56
|
assert_same_size_text first_secret, check_secret
|
data/lib/keytools/key.rb
CHANGED
@@ -316,8 +316,8 @@ module OpenKey
|
|
316
316
|
#
|
317
317
|
# This method should only ever be called when this key has been derived
|
318
318
|
# from either a (huge) <b>48 byte random source</b> or from a key derivation
|
319
|
-
# function (KDF) such as BCrypt, SCrypt, PBKDF2 or a union from
|
320
|
-
#
|
319
|
+
# function (KDF) such as BCrypt, SCrypt, PBKDF2 or a union from which the
|
320
|
+
# 512 bit (64 byte) key can be reduced to 256 bits.
|
321
321
|
#
|
322
322
|
# @return [String]
|
323
323
|
# a binary string of thirty-two (32) eight (8) bit bytes which
|
@@ -407,24 +407,12 @@ module OpenKey
|
|
407
407
|
calling_lineno = caller_locations(1,1).first.lineno
|
408
408
|
caller_details = "#{calling_module} | #{calling_method} | (line #{calling_lineno})"
|
409
409
|
|
410
|
-
log.info(x) { "### #####################################################################" }
|
411
|
-
log.info(x) { "### Caller Details =>> =>> #{caller_details}" }
|
412
|
-
log.info(x) { "### #####################################################################" }
|
413
|
-
log.info(x) { "The BitStr Char representation of this key => #{to_s()}" }
|
414
|
-
log.info(x) { "256bit Digest (Urlsafe Base64) of this key => #{Base64.urlsafe_encode64(to_aes_key())}" }
|
415
|
-
log.info(x) { "The IncomingKey Base64 Char representation => #{key_to_encrypt.to_char64()}" }
|
416
|
-
log.info(x) { "Random IV Used for the AESs Key Encryption => #{Base64.urlsafe_encode64(random_iv)}" }
|
417
|
-
|
418
410
|
cipher_text = crypt_cipher.update( key_to_encrypt.to_char64 ) + crypt_cipher.final
|
419
|
-
log.info(x) { "Cipher Text Produced after this Encryption => #{Base64.urlsafe_encode64(cipher_text)}" }
|
420
411
|
|
421
412
|
binary_text = random_iv + cipher_text
|
422
413
|
ones_zeroes = binary_text.unpack("B*")[0]
|
423
414
|
ciphertxt64 = Key64.from_bits( ones_zeroes )
|
424
415
|
|
425
|
-
log.info(x) { "Amalgam of Binary Random IV and Ciphertext => #{ciphertxt64}" }
|
426
|
-
log.info(x) { "------------------------------------------------------------------------- >>>>>>" }
|
427
|
-
|
428
416
|
size_msg = "Expected bit count is #{EXPECTED_CIPHER_BIT_LENGTH} not #{ones_zeroes.length}."
|
429
417
|
raise RuntimeError, size_msg unless ones_zeroes.length == EXPECTED_CIPHER_BIT_LENGTH
|
430
418
|
|
@@ -468,18 +456,6 @@ module OpenKey
|
|
468
456
|
# the size of the parameter ciphertext must be 128 base 64 characters.
|
469
457
|
def do_decrypt_key ciphertext_to_decrypt
|
470
458
|
|
471
|
-
calling_module = File.basename caller_locations(1,1).first.absolute_path, ".rb"
|
472
|
-
calling_method = caller_locations(1,1).first.base_label
|
473
|
-
calling_lineno = caller_locations(1,1).first.lineno
|
474
|
-
caller_details = "#{calling_module} | #{calling_method} | (line #{calling_lineno})"
|
475
|
-
|
476
|
-
log.info(x) { "### #####################################################################" }
|
477
|
-
log.info(x) { "### Caller Details =>> =>> #{caller_details}" }
|
478
|
-
log.info(x) { "### #####################################################################" }
|
479
|
-
log.info(x) { "Amalgam of Binary Random IV and Ciphertext => #{ciphertext_to_decrypt}" }
|
480
|
-
log.info(x) { "The Base64 Char representation of this key => #{to_s()}" }
|
481
|
-
log.info(x) { "256bit Digest (Urlsafe Base64) of this key => #{Base64.urlsafe_encode64(to_aes_key())}" }
|
482
|
-
|
483
459
|
bit_text = Key64.to_bits(ciphertext_to_decrypt)
|
484
460
|
size_msg = "Expected bit count is #{EXPECTED_CIPHER_BIT_LENGTH} not #{bit_text.length}."
|
485
461
|
raise RuntimeError, size_msg unless bit_text.length == EXPECTED_CIPHER_BIT_LENGTH
|
@@ -493,8 +469,6 @@ module OpenKey
|
|
493
469
|
cipher_x.iv = rawbytes[ 0 .. ( RANDOM_IV_BYTE_COUNT - 1 ) ]
|
494
470
|
key_chars_64 = cipher_x.update( rawbytes[ RANDOM_IV_BYTE_COUNT .. -1 ] ) + cipher_x.final
|
495
471
|
|
496
|
-
log.info(x) { "The OutgoingKey Base64 Char representation => #{key_chars_64}" }
|
497
|
-
|
498
472
|
return Key.from_char64( key_chars_64 )
|
499
473
|
|
500
474
|
end
|
File without changes
|
data/lib/session/fact.finder.rb
CHANGED
@@ -1,21 +1,6 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
|
4
|
-
# (serverless) session. Configuration directives are read and written
|
5
|
-
# from an INI off the home directory that is created when the session
|
6
|
-
# is first initiated.
|
7
|
-
#
|
8
|
-
# The session is expected to be formally closed down and that is
|
9
|
-
# reflected by explicitly deleting the configuration file. If this
|
10
|
-
# "session over" command is not issued a reasonable time limit is
|
11
|
-
# then invoked when the next session command is issued.
|
12
|
-
#
|
13
|
-
# This "session awakening" wipes the slate clean and starts afresh
|
14
|
-
# with regard to the two dimensional array of configuration directive
|
15
|
-
# pointers.
|
16
|
-
module OpenSession
|
17
|
-
|
18
|
-
require "pp"
|
3
|
+
module OpenSecret
|
19
4
|
|
20
5
|
# --
|
21
6
|
# -- -----------------
|
@@ -64,85 +49,23 @@ module OpenSession
|
|
64
49
|
# --
|
65
50
|
# --
|
66
51
|
class FactFind
|
67
|
-
include Singleton
|
68
52
|
|
69
53
|
@@eval_prefix = "rb>>"
|
70
|
-
attr_reader :i, :f
|
71
|
-
|
72
|
-
# --
|
73
|
-
# -- Initialize the internal fact database
|
74
|
-
# -- which is exposed for fact consumption
|
75
|
-
# -- via
|
76
|
-
# --
|
77
|
-
# -- @i => [identity] facts (1D)
|
78
|
-
# -- @n => (reserved perhaps 4 nested facts)
|
79
|
-
# -- @f => [file facts] database (2D)
|
80
|
-
# -- @a => (reserved)
|
81
|
-
# -- @c => coded consumtion (in software)
|
82
|
-
# -- @t => template placeholders (2D)
|
83
|
-
# -- @s => sibling (same category) facts (1D)
|
84
|
-
# --
|
85
|
-
def instantiate plugin_id
|
86
|
-
|
87
|
-
@i = { :plugin => plugin_id,
|
88
|
-
:time => Stamp.yyjjj_hhmm_sst,
|
89
|
-
:user => Home.usr,
|
90
|
-
:station => nil
|
91
|
-
}
|
92
54
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
@f.store symbol(plugin_id), {}
|
98
|
-
@p = @f[symbol(plugin_id)]
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
#--
|
106
|
-
#-- Set the main directory path.
|
107
|
-
#-- This method adds the parameter path to
|
108
|
-
#-- the identity map. After this method
|
109
|
-
#-- executes you will be able to access the
|
110
|
-
#-- directory with @i[:dir]
|
111
|
-
#--
|
112
|
-
def add_dir_to_identity key_directory
|
113
|
-
@i[:dir] = key_directory
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
# --
|
119
|
-
# --
|
120
|
-
# --
|
121
|
-
def assimilate_plugin_facts
|
122
|
-
|
123
|
-
plugin_fact_filepath = File.join @i[:src_dir], "#{@i[:plugin]}.ini"
|
124
|
-
log.info(x) { "Plugin Factfile => #{plugin_fact_filepath}" }
|
125
|
-
assimilate_ini_file plugin_fact_filepath
|
55
|
+
# The fact tree values can be referenced using the @f
|
56
|
+
# specifier with a 2 dimensional key.
|
57
|
+
attr_reader :f
|
126
58
|
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
# --
|
131
|
-
# --
|
132
|
-
# --
|
133
|
-
def assimilate_general_facts
|
134
59
|
|
135
|
-
|
60
|
+
# This method constructs the FactFind object and tree database
|
61
|
+
# and initializers the root fact container structures.
|
62
|
+
def initialize
|
136
63
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
log.info(x) {"Assimilating facts from => [#{file_name}]"}
|
141
|
-
factfile_path = File.join factfiles_map[file_name], file_name
|
142
|
-
log.info(x) {"Factfile location => [#{nickname factfile_path}]"}
|
143
|
-
assimilate_ini_file factfile_path
|
64
|
+
@f = {}
|
65
|
+
@s = {}
|
144
66
|
|
145
|
-
|
67
|
+
# ---> @f.store symbol(plugin_id), {}
|
68
|
+
# ---> @p = @f[symbol(plugin_id)]
|
146
69
|
|
147
70
|
end
|
148
71
|
|
@@ -171,162 +94,6 @@ module OpenSession
|
|
171
94
|
end
|
172
95
|
|
173
96
|
|
174
|
-
# --
|
175
|
-
# -- Assimilate [[ hub-runtime.ini ]]
|
176
|
-
# -- This factfile builds upon the (fundamental) handful of
|
177
|
-
# -- identity facts. It derives the facts for
|
178
|
-
# --
|
179
|
-
# -- - the plugin instance folder
|
180
|
-
# -- - the instance stamp id keys
|
181
|
-
# --
|
182
|
-
# -- The instance fact file is not allowed to harbour any
|
183
|
-
# -- external dependencies.
|
184
|
-
# --
|
185
|
-
def assimilate_instance_facts
|
186
|
-
|
187
|
-
instance_facts_file = fact_path("hub-runtime.ini")
|
188
|
-
log.info(x) { "Path to instance facts file => #{instance_facts_file}" }
|
189
|
-
assimilate_ini_file instance_facts_file
|
190
|
-
|
191
|
-
end
|
192
|
-
|
193
|
-
|
194
|
-
# --
|
195
|
-
# -- -----------------------------------
|
196
|
-
# -- Finding the Workstation (Category)
|
197
|
-
# -- -----------------------------------
|
198
|
-
# --
|
199
|
-
# -- The known hosts facts file is parsed with each
|
200
|
-
# -- section [examined] by asking two (2) questions.
|
201
|
-
# --
|
202
|
-
# -- [1] - is [username] this workstation's username?
|
203
|
-
# -- [2] - does [hostnames] include this hostname?
|
204
|
-
# --
|
205
|
-
# -- The 1st section to answer [YES] to both questions
|
206
|
-
# -- is deemed as our workstation. Its symbol header is
|
207
|
-
# -- then used for assimilation - how?
|
208
|
-
# --
|
209
|
-
# -- ----------------------------------------
|
210
|
-
# -- Assimilating Workstation Specific Facts
|
211
|
-
# -- ----------------------------------------
|
212
|
-
# --
|
213
|
-
# -- We do NOT assimilate the whole file.
|
214
|
-
# -- We simply assimilate the [SECTION] of the file
|
215
|
-
# -- that is deemed to be OUR (this) workstation.
|
216
|
-
# --
|
217
|
-
# -- -------------------------------------------
|
218
|
-
# -- Dependency Constraints | Workstation Facts
|
219
|
-
# -- -------------------------------------------
|
220
|
-
# --
|
221
|
-
# -- (work)station facts can [only] depend on facts that
|
222
|
-
# -- have been declared in [[ hub-runtime.ini ]]. No
|
223
|
-
# -- other external fact dependencies are permitted.
|
224
|
-
# --
|
225
|
-
def identify_my_workstation
|
226
|
-
|
227
|
-
workstation_factfile_name = "known-hosts.ini"
|
228
|
-
log_begin_workstation_identification workstation_factfile_name
|
229
|
-
stations_factfile = fact_path workstation_factfile_name
|
230
|
-
log.info(x) { "Workstations Facts File (Path) => #{nickname stations_factfile}" }
|
231
|
-
|
232
|
-
our_user = Home.usr
|
233
|
-
our_host = NetDns.instance.host_name
|
234
|
-
log.info(x){ "Station Search For => #{our_user}@#{our_host}" }
|
235
|
-
|
236
|
-
workstations = IniFile.load stations_factfile
|
237
|
-
workstations.each_section do |station|
|
238
|
-
|
239
|
-
no_user = "Workstation [#{station}] has no [username] fact."
|
240
|
-
raise RuntimeError.new no_user unless workstations[station].has_key? "username"
|
241
|
-
|
242
|
-
has_hostnames = workstations[station].has_key? "hostnames"
|
243
|
-
no_hostnames = "[#{station}] not a workstation as no [hostnames] fact - Skip!"
|
244
|
-
log.warn(x) { no_hostnames } unless has_hostnames
|
245
|
-
next unless has_hostnames
|
246
|
-
|
247
|
-
this_user = evaluate(workstations[station]["username"])
|
248
|
-
these_hosts = evaluate(workstations[station]["hostnames"])
|
249
|
-
match = this_user.eql?(our_user) && these_hosts.include?(our_host)
|
250
|
-
|
251
|
-
log.info(x){ "[#{station}] with #{this_user}@#{these_hosts} - No!" } unless match
|
252
|
-
next unless match
|
253
|
-
|
254
|
-
log.info(x){ "[#{station}] with #{this_user}@#{these_hosts} - Matched!" }
|
255
|
-
dup_msg = "Duplicate or repeat match disallowed! #{@i[:station]} and #{station}"
|
256
|
-
raise RuntimeError.new dup_msg unless @i[:station].nil?
|
257
|
-
|
258
|
-
@i[:station] = station
|
259
|
-
@i[:workstation] = station.gsub(".", "_").to_sym
|
260
|
-
|
261
|
-
end
|
262
|
-
|
263
|
-
no_match_msg = "No workstation match made for [#{our_user}@#{our_host}]."
|
264
|
-
raise RuntimeError.new no_match_msg if @i[:station].nil?
|
265
|
-
log_end_workstation_identification workstation_factfile_name
|
266
|
-
LogObject.map @i
|
267
|
-
|
268
|
-
end
|
269
|
-
|
270
|
-
|
271
|
-
#--
|
272
|
-
#-- Knowing and setting @i[:workstation] to our workstation is key.
|
273
|
-
#-- This means that the other workstations can reference files in
|
274
|
-
#-- each others drives without knowing which workstation is being
|
275
|
-
#-- used (see ssh.keyfile for a ghost reference example).
|
276
|
-
#--
|
277
|
-
#-- Now we can proceed to assimilate the entire station facts file.
|
278
|
-
#--
|
279
|
-
def assimilate_station_facts
|
280
|
-
|
281
|
-
stations_factfile = fact_path "known-hosts.ini"
|
282
|
-
assimilate_ini_file stations_factfile
|
283
|
-
|
284
|
-
end
|
285
|
-
|
286
|
-
|
287
|
-
# --
|
288
|
-
# -- Get the path to a fact file or folder within the
|
289
|
-
# -- reusable facts source tree.
|
290
|
-
# --
|
291
|
-
# -- The base directory is acquired by dropping down
|
292
|
-
# -- three (3) directory levels from where this module
|
293
|
-
# -- is and then going into reusable.facts and finally
|
294
|
-
# -- appending the parameter path (file or folder).
|
295
|
-
# --
|
296
|
-
def fact_path fact_filename
|
297
|
-
fact_basedir = File.dirname( File.dirname( File.dirname( __FILE__ ) ) )
|
298
|
-
return File.join( File.join(fact_basedir,"reusable.facts"), fact_filename )
|
299
|
-
end
|
300
|
-
|
301
|
-
|
302
|
-
# --
|
303
|
-
# -- Call instantiate() before calling populate().
|
304
|
-
# --
|
305
|
-
# -- This method assimilates any and all fact files
|
306
|
-
# -- (recursively) found in two subdirectories
|
307
|
-
# --
|
308
|
-
# -- [1] - "reusable facts" and
|
309
|
-
# -- [2] - the [plugin] folder
|
310
|
-
# --
|
311
|
-
def self.populate
|
312
|
-
|
313
|
-
end
|
314
|
-
|
315
|
-
|
316
|
-
# -- -------------------------------------------------------------- -- #
|
317
|
-
# -- Eval and return result of parameter string if it is ruby code. -- #
|
318
|
-
# -- -------------------------------------------------------------- -- #
|
319
|
-
def evaluate string
|
320
|
-
|
321
|
-
# -----> @todo raise a FactError here
|
322
|
-
|
323
|
-
raise RuntimeError.new "Fact to Evaluate is Nil." if string.nil?
|
324
|
-
return string unless string.start_with? @@eval_prefix
|
325
|
-
return eval( string.gsub @@eval_prefix, "" )
|
326
|
-
|
327
|
-
end
|
328
|
-
|
329
|
-
|
330
97
|
# ----> -------------------------------------------------->
|
331
98
|
# ----> How to Write a Custom Error
|
332
99
|
# ----> -------------------------------------------------->
|
@@ -350,44 +117,6 @@ module OpenSession
|
|
350
117
|
# ----> -------------------------------------------------->
|
351
118
|
|
352
119
|
|
353
|
-
# -- ---------------------------------------- -- #
|
354
|
-
# -- Add a fact to the main 2D fact database. -- #
|
355
|
-
# -- ---------------------------------------- -- #
|
356
|
-
def add_fact group_symbol, key_symbol, key_value
|
357
|
-
|
358
|
-
nil_error_text = "Neither fact coordinates nor value can be nil. [group]=> #{group_symbol} [key]=> #{key_symbol} [value]=> #{key_value}"
|
359
|
-
raise ArgumentError.new nil_error_text if group_symbol.nil? || key_symbol.nil? || key_value.nil?
|
360
|
-
|
361
|
-
if @f.has_key? group_symbol then
|
362
|
-
|
363
|
-
# --
|
364
|
-
# -- This isn't the first fact within this group
|
365
|
-
# -- so store the new fact key/value pair within
|
366
|
-
# -- the group's namespace.
|
367
|
-
# --
|
368
|
-
@f[group_symbol][key_symbol] = key_value
|
369
|
-
|
370
|
-
else
|
371
|
-
|
372
|
-
# --
|
373
|
-
# -- Create a new umbrella grouping against which
|
374
|
-
# -- the new key-value pairing will be inserted.
|
375
|
-
# --
|
376
|
-
@f.store group_symbol, { key_symbol => key_value }
|
377
|
-
|
378
|
-
end
|
379
|
-
|
380
|
-
# --
|
381
|
-
# -- The @s sibling hash is updated to reflect the
|
382
|
-
# -- key-value pairs within the current group. This
|
383
|
-
# -- allows @s to be used as shorthand within INI
|
384
|
-
# -- file fact definition statements.
|
385
|
-
# --
|
386
|
-
@s = @f[group_symbol]
|
387
|
-
|
388
|
-
end
|
389
|
-
|
390
|
-
|
391
120
|
# -- ------------------------------------------- -- #
|
392
121
|
# -- -- #
|
393
122
|
# -- Template -- #
|
@@ -458,30 +187,39 @@ module OpenSession
|
|
458
187
|
|
459
188
|
|
460
189
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
190
|
+
# This method assimilates a two-dimensional fact bringing it into the
|
191
|
+
# fact tree fold.
|
192
|
+
#
|
193
|
+
# Once assimilated, this fact with a 2D index can be reused
|
194
|
+
# - for future fact resolution
|
195
|
+
# - by classes with access to the fact tree
|
196
|
+
# - for dynamic template resolution
|
197
|
+
#
|
198
|
+
# @param fact_group_str the first dimensional fact key
|
199
|
+
# @param fact_key_str the second dimensional fact key
|
200
|
+
# @param fact_value_str value of the fact to assimilate
|
201
|
+
def assimilate_fact fact_group_str, fact_key_str, fact_value_str
|
465
202
|
|
466
|
-
|
203
|
+
grp_symbol = fact_group_str.gsub(".", "_").to_sym
|
204
|
+
key_symbol = fact_key_str.gsub(".", "_").to_sym
|
467
205
|
|
468
|
-
|
206
|
+
raise ArgumentError, "Assimilating Fact [ #{fact_group_str} ][ #{fact_key_str} ] => Value is NIL" if fact_value_str.nil?
|
207
|
+
fact_string = fact_value_str.strip
|
469
208
|
|
470
209
|
begin
|
471
210
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
end
|
211
|
+
raise ArgumentError, "Fact object in section #{fact_group_str} with key #{fact_key_str} is nil." if fact_string.nil?
|
212
|
+
eval_value = evaluate( fact_string )
|
213
|
+
add_fact grp_symbol, to_symbol(fact_key_str), eval_value
|
476
214
|
|
477
215
|
rescue Exception => e
|
478
216
|
|
479
217
|
log.fatal(x) { "## ##################### #################################" }
|
480
218
|
log.fatal(x) { "## Fact Evaluation Error ---------------------------------" }
|
481
219
|
log.fatal(x) { "## ##################### #################################" }
|
482
|
-
log.fatal(x) { "## Fact Family => #{
|
483
|
-
log.fatal(x) { "## Fact Key => #{
|
484
|
-
log.fatal(x) { "## Fact Stmt => #{
|
220
|
+
log.fatal(x) { "## Fact Family => #{fact_group_str}" }
|
221
|
+
log.fatal(x) { "## Fact Key => #{fact_key_str}" }
|
222
|
+
log.fatal(x) { "## Fact Stmt => #{fact_string}" }
|
485
223
|
log.fatal(x) { "## Fact Error => #{e.message}" }
|
486
224
|
log.fatal(x) { "## ##################### #################################" }
|
487
225
|
e.backtrace.log_lines
|
@@ -492,9 +230,9 @@ module OpenSession
|
|
492
230
|
|
493
231
|
unless @f.has_key? grp_symbol then
|
494
232
|
|
495
|
-
log.debug(x){ "#
|
496
|
-
log.debug(x){ "#
|
497
|
-
log.debug(x){ "#
|
233
|
+
log.debug(x){ "# @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #" }
|
234
|
+
log.debug(x){ "# @@ the [#{fact_group_str}] silo facts." }
|
235
|
+
log.debug(x){ "# @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #" }
|
498
236
|
|
499
237
|
end
|
500
238
|
|
@@ -503,164 +241,63 @@ module OpenSession
|
|
503
241
|
print_value = "****************"
|
504
242
|
print_value = eval_value unless sensitive
|
505
243
|
|
506
|
-
# -- -------------------------------------------------------- -- #
|
507
|
-
# -- Log the human readable (fixed-width) key and value pair. -- #
|
508
|
-
# -- -------------------------------------------------------- -- #
|
509
244
|
fw_key = sprintf '%-33s', "@f[:#{grp_symbol}][:#{key_symbol}]"
|
510
245
|
log.debug(x){ "#{fw_key} => #{print_value}" }
|
511
246
|
|
512
247
|
end
|
513
248
|
|
514
249
|
|
515
|
-
def discard_fact? group_str, key_str, input_value
|
516
|
-
|
517
|
-
is_if = key_str.strip.end_with? "(if)"
|
518
|
-
is_unless = key_str.strip.end_with?("(un)") || key_str.strip.end_with?("(unless)")
|
519
|
-
return false unless is_if || is_unless
|
520
|
-
|
521
|
-
two_parts = input_value.split( @@eval_prefix )
|
522
|
-
no_prefix = "Conditional must be followed by eval prefix => #{two_parts}"
|
523
|
-
raise RuntimeError.new no_pefix unless two_parts.length == 2
|
524
|
-
|
525
|
-
conditional_part = two_parts.first.strip
|
526
|
-
no_curlies_msg = "Wrap conditional in curly braces => #{conditional_part}"
|
527
|
-
is_wrapped = conditional_part.start_with?("{") && conditional_part.end_with?("}")
|
528
|
-
raise RuntimeError.new no_curlies_msg unless is_wrapped
|
529
|
-
|
530
|
-
conditional_stmt = conditional_part[1..-2].strip
|
531
|
-
log.info(x){ "Conditional Stmt => #{conditional_stmt}" }
|
532
|
-
conditional_val = evaluate( @@eval_prefix + conditional_stmt )
|
533
|
-
is_boolean = [true, false].include? conditional_val
|
534
|
-
|
535
|
-
boolean_msg = "=> #{conditional_stmt} <= evaluated to [#{conditional_val}] not boolean."
|
536
|
-
raise RuntimeError.new boolean_msg unless is_boolean
|
537
|
-
|
538
|
-
return false if is_if && conditional_val
|
539
|
-
return true if is_if && !conditional_val
|
540
|
-
|
541
|
-
return true if is_unless && conditional_val
|
542
|
-
return false if is_unless && !conditional_val
|
543
|
-
|
544
|
-
raise RuntimeError.new "Unreachable if[#{is_if}] unless[#{is_unless}] => #{conditional_val}"
|
545
|
-
|
546
|
-
end
|
547
|
-
|
548
|
-
|
549
|
-
#--
|
550
|
-
#-- Return the symbolic representation of the
|
551
|
-
#-- parameter key. Periods are replaced with
|
552
|
-
#-- underscores (as per the fact convention)
|
553
|
-
#-- before conversion to a symbol.
|
554
|
-
#--
|
555
|
-
#-- Nil is not handled.
|
556
|
-
#-- String is stripped beforehand just in case.
|
557
|
-
#--
|
558
|
-
def symbol from_string
|
559
250
|
|
251
|
+
# This static method converts from string to symbol.
|
252
|
+
# @param from_string the neither nil nor empty string to convert to a symbol
|
253
|
+
# @return a symbol representation of the input string
|
254
|
+
def to_symbol from_string
|
560
255
|
return from_string.strip.gsub(".", "_").to_sym
|
561
|
-
|
562
256
|
end
|
563
257
|
|
564
258
|
|
565
|
-
#--
|
566
|
-
#-- Return the (key access) symbol that represents the
|
567
|
-
#-- plugin id plus a string given in the parameter.
|
568
|
-
#--
|
569
|
-
#-- ---------
|
570
|
-
#-- Example
|
571
|
-
#-- ---------
|
572
|
-
#--
|
573
|
-
#-- Plugin Id => ide.hub
|
574
|
-
#-- Append Str => host
|
575
|
-
#--
|
576
|
-
#-- equals
|
577
|
-
#--
|
578
|
-
#-- Key String => ide.hub.host
|
579
|
-
#-- Key Symbol => ide_hub_host
|
580
|
-
#--
|
581
|
-
#--
|
582
|
-
#-- So the symbol :ide_hub_host is returned.
|
583
|
-
#--
|
584
|
-
def plugin_symbol append_string
|
585
|
-
|
586
|
-
key_string = @i[:plugin] + "." + append_string.strip
|
587
|
-
return key_string.gsub(".", "_").to_sym
|
588
|
-
|
589
|
-
end
|
590
|
-
|
591
259
|
|
592
|
-
|
260
|
+
private
|
593
261
|
|
594
|
-
key_string = dirty_key_string.strip
|
595
|
-
split_string = "(unless)"
|
596
|
-
split_string = "(if)" if key_string.end_with? "(if)"
|
597
|
-
split_string = "(un)" if key_string.end_with? "(un)"
|
598
262
|
|
599
|
-
return key_string.split(split_string).first.gsub(".", "_").to_sym
|
600
263
|
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
def get_fact_value fact_value_string
|
605
|
-
|
606
|
-
is_conditional = fact_value_string.start_with?("{") && fact_value_string.include?( @@eval_prefix )
|
607
|
-
return fact_value_string unless is_conditional
|
608
|
-
|
609
|
-
return fact_value_string.rpartition( @@eval_prefix )[1..-1].join
|
610
|
-
|
611
|
-
end
|
264
|
+
def add_fact group_symbol, key_symbol, key_value
|
612
265
|
|
266
|
+
fact_component = "[group]=> #{group_symbol} [key]=> #{key_symbol} [value]=> #{key_value}"
|
267
|
+
nil_error_text = "Neither fact coordinates nor values can be nil. #{fact_component}"
|
268
|
+
raise ArgumentError.new nil_error_text if group_symbol.nil? || key_symbol.nil? || key_value.nil?
|
613
269
|
|
614
|
-
|
270
|
+
if @f.has_key? group_symbol then
|
615
271
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
272
|
+
# -- This isn't the first fact within this group
|
273
|
+
# -- so store the new fact key/value pair within
|
274
|
+
# -- the group's namespace.
|
275
|
+
@f[group_symbol][key_symbol] = key_value
|
620
276
|
|
621
|
-
|
277
|
+
else
|
622
278
|
|
279
|
+
# -- Create a new umbrella grouping against which
|
280
|
+
# -- the new key-value pairing will be inserted.
|
281
|
+
@f.store group_symbol, { key_symbol => key_value }
|
623
282
|
|
624
|
-
|
625
|
-
# -- dot => period (full stop)
|
626
|
-
# -- Deliver a "." period character
|
627
|
-
# --
|
628
|
-
def dot
|
629
|
-
return "."
|
630
|
-
end
|
283
|
+
end
|
631
284
|
|
285
|
+
# -- The @s sibling hash is updated to reflect the
|
286
|
+
# -- key-value pairs within the current group. This
|
287
|
+
# -- allows @s to be used as shorthand within INI
|
288
|
+
# -- file fact definition statements.
|
289
|
+
@s = @f[group_symbol]
|
632
290
|
|
633
|
-
# --
|
634
|
-
# -- colon => full colon character
|
635
|
-
# -- Delivers a ":" colon character
|
636
|
-
# --
|
637
|
-
def colon
|
638
|
-
return ":"
|
639
291
|
end
|
640
292
|
|
641
293
|
|
642
|
-
def
|
643
|
-
|
644
|
-
log.info(x) { "- -" }
|
645
|
-
log.info(x) { "# @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ #" }
|
646
|
-
log.info(x) { "# -- ------------------------------------------------- -- #" }
|
647
|
-
log.info(x) { "# -- [= BEGIN WORKSTATION IDENTIFICATION =] #{the_filename}" }
|
648
|
-
log.info(x) { "# -- ------------------------------------------------- -- #" }
|
649
|
-
log.info(x) { "# @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ #" }
|
650
|
-
|
651
|
-
end
|
652
|
-
|
294
|
+
def evaluate string
|
653
295
|
|
654
|
-
|
296
|
+
# -----> @todo raise a FactError here
|
655
297
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
log.info(x) { "# -- ------------------------------------------------- -- #" }
|
660
|
-
log.info(x) { "# @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ #" }
|
661
|
-
log.info(x) { "- -" }
|
662
|
-
log.info(x) { "- -" }
|
663
|
-
log.info(x) { "- -" }
|
298
|
+
raise RuntimeError.new "Fact to Evaluate is Nil." if string.nil?
|
299
|
+
return string unless string.start_with? @@eval_prefix
|
300
|
+
return eval( string.gsub @@eval_prefix, "" )
|
664
301
|
|
665
302
|
end
|
666
303
|
|