dtk-client 0.6.8 → 0.7.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.
- checksums.yaml +8 -8
- data/bin/dtk +5 -1
- data/lib/auxiliary.rb +0 -1
- data/lib/commands/common/thor/assembly_workspace.rb +20 -1
- data/lib/commands/common/thor/inventory_parser.rb +1 -1
- data/lib/commands/common/thor/module/import.rb +41 -106
- data/lib/commands/common/thor/module.rb +13 -226
- data/lib/commands/common/thor/poller.rb +48 -0
- data/lib/commands/common/thor/puppet_forge.rb +7 -1
- data/lib/commands/common/thor/purge_clone.rb +2 -1
- data/lib/commands/common/thor/task_status.rb +15 -14
- data/lib/commands/common/thor/test_action_agent.rb +39 -0
- data/lib/commands/thor/component_module.rb +2 -2
- data/lib/commands/thor/node.rb +55 -14
- data/lib/commands/thor/node_group.rb +2 -26
- data/lib/commands/thor/service.rb +31 -11
- data/lib/commands/thor/service_module.rb +3 -1
- data/lib/commands/thor/workspace.rb +13 -3
- data/lib/core.rb +16 -6
- data/lib/domain/git_adapter.rb +0 -3
- data/lib/domain/response.rb +25 -13
- data/lib/dtk-client/version.rb +1 -1
- data/lib/parser/adapters/thor.rb +8 -5
- data/lib/shell/context.rb +8 -19
- data/lib/shell/domain/active_context.rb +169 -0
- data/lib/shell/domain/context_entity.rb +72 -0
- data/lib/shell/domain/context_params.rb +202 -0
- data/lib/shell/domain/override_tasks.rb +71 -0
- data/lib/shell/domain/shadow_entity.rb +59 -0
- data/lib/shell/help_monkey_patch.rb +76 -71
- data/lib/shell/message_queue.rb +2 -0
- data/lib/shell/status_monitor.rb +5 -3
- data/lib/shell.rb +4 -2
- data/lib/util/dtk_puppet.rb +8 -6
- data/lib/util/os_util.rb +5 -1
- data/lib/view_processor/table_print.rb +67 -12
- data/spec/lib/spec_thor.rb +5 -2
- metadata +9 -3
- data/lib/shell/domain.rb +0 -492
data/lib/shell/domain.rb
DELETED
@@ -1,492 +0,0 @@
|
|
1
|
-
module DTK
|
2
|
-
module Shell
|
3
|
-
|
4
|
-
class ContextParams
|
5
|
-
|
6
|
-
attr_accessor :current_context
|
7
|
-
attr_accessor :method_arguments
|
8
|
-
|
9
|
-
def initialize(override_method_arguments = [])
|
10
|
-
@current_context = ActiveContext.new
|
11
|
-
@method_arguments = override_method_arguments
|
12
|
-
@thor_options = Hash.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def add_context_to_params(context_name, entity_name, context_value = nil)
|
16
|
-
@current_context.push_new_context(context_name, stand_name(entity_name), context_value)
|
17
|
-
end
|
18
|
-
|
19
|
-
def add_context_name_to_params(context_name, entity_name, context_value = nil)
|
20
|
-
@current_context.push_new_name_context(context_name, stand_name(entity_name), context_value)
|
21
|
-
end
|
22
|
-
|
23
|
-
def forward_options(options)
|
24
|
-
@thor_options = options
|
25
|
-
end
|
26
|
-
|
27
|
-
def get_forwarded_options()
|
28
|
-
@thor_options
|
29
|
-
end
|
30
|
-
|
31
|
-
def get_forwarded_thor_option(option_key)
|
32
|
-
return @thor_options ? @thor_options[option_key] : nil
|
33
|
-
end
|
34
|
-
|
35
|
-
def override_method_argument!(key, value)
|
36
|
-
id = match_argument_id(key)
|
37
|
-
raise DTK::Client::DtkImplementationError, "Wrong identifier used '#{key}', ID not matched!" unless id
|
38
|
-
@method_arguments[id] = value
|
39
|
-
end
|
40
|
-
|
41
|
-
# can be class methods but no need, since we have this instance available in each method
|
42
|
-
def retrieve_thor_options(mapping, options)
|
43
|
-
results = []
|
44
|
-
errors = []
|
45
|
-
|
46
|
-
mapping.each do |key|
|
47
|
-
required = key.to_s.match(/.+!$/)
|
48
|
-
thor_key = key.to_s.gsub('!','')
|
49
|
-
|
50
|
-
results << element = options[thor_key]
|
51
|
-
|
52
|
-
if required && element.nil?
|
53
|
-
errors << thor_key
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
unless errors.empty?
|
58
|
-
raise DTK::Client::DtkValidationError.new("Missing required option#{errors.size > 1 ? 's' : ''}: #{errors.join(', ')}", true)
|
59
|
-
end
|
60
|
-
|
61
|
-
return ((results.size == 1) ? results.first : results)
|
62
|
-
end
|
63
|
-
|
64
|
-
def retrieve_arguments(mapping, method_info = [])
|
65
|
-
results = []
|
66
|
-
errors = []
|
67
|
-
|
68
|
-
# using context_name when have array as key_mapping [:assembly_id, :workspace_id]
|
69
|
-
# to determine which context is used
|
70
|
-
context_name = method_info.first.split('-').first unless method_info.empty?
|
71
|
-
|
72
|
-
mapping.each do |key_mapping|
|
73
|
-
|
74
|
-
is_array = key_mapping.is_a?(Array)
|
75
|
-
|
76
|
-
selected_key = is_array ? key_mapping.first : key_mapping
|
77
|
-
|
78
|
-
required = selected_key.to_s.match(/.+!$/)
|
79
|
-
|
80
|
-
element = nil
|
81
|
-
matched = selected_key.to_s.match(/option_([0-9]+)/)
|
82
|
-
if matched
|
83
|
-
id = matched[1].to_i - 1
|
84
|
-
element = @method_arguments[id]
|
85
|
-
|
86
|
-
# used if last parameter has more than one word
|
87
|
-
# e.g. set-attribute attr_name "some value" (thor separates 'some value' as two parameters but we need it as one)
|
88
|
-
if(mapping.last.to_s.eql?(key_mapping.to_s))
|
89
|
-
new_id = id+1
|
90
|
-
while @method_arguments[new_id] do
|
91
|
-
element << " #{@method_arguments[new_id]}"
|
92
|
-
new_id += 1;
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
unless method_info.empty?
|
97
|
-
unless element
|
98
|
-
errors << method_info[id] if required
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
else
|
103
|
-
# More complex split regex for extracting entitiy name from mapping due to complex context names
|
104
|
-
# i.e. assembly-template will have assembly_template_id mapping
|
105
|
-
element = check_context_for_element(selected_key)
|
106
|
-
|
107
|
-
# if we are dealing with array we need to check rest of the keys since it is OR
|
108
|
-
# approach if first element not found take second
|
109
|
-
if element.nil? && is_array
|
110
|
-
key_mapping[1..-1].each do |alternative_key|
|
111
|
-
element = check_context_for_element(alternative_key)
|
112
|
-
break if element
|
113
|
-
if context_name
|
114
|
-
if alternative_key.to_s.include?(context_name.downcase)
|
115
|
-
required = alternative_key.to_s.match(/.+!$/)
|
116
|
-
selected_key = alternative_key
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
unless element
|
123
|
-
errors << "#{entity_name(selected_key).upcase} ID/NAME" if required
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
results << element
|
128
|
-
end
|
129
|
-
|
130
|
-
unless errors.empty?
|
131
|
-
raise DTK::Client::DtkValidationError.new("Missing required argument#{errors.size > 1 ? 's' : ''}: #{errors.join(', ')}", true)
|
132
|
-
end
|
133
|
-
|
134
|
-
return ((results.size == 1) ? results.first : results)
|
135
|
-
end
|
136
|
-
|
137
|
-
def is_last_command_eql_to?(command_name)
|
138
|
-
return @current_context.last_command_name() == command_name.to_s
|
139
|
-
end
|
140
|
-
|
141
|
-
def is_there_identifier?(entity_name)
|
142
|
-
return @current_context.find_identifier(entity_name) != nil
|
143
|
-
end
|
144
|
-
|
145
|
-
def is_there_command?(entity_name)
|
146
|
-
return @current_context.find_command(entity_name) != nil
|
147
|
-
end
|
148
|
-
def current_command?
|
149
|
-
return @current_context.current_command?
|
150
|
-
end
|
151
|
-
def root_command_name
|
152
|
-
@current_context.first_command_name
|
153
|
-
end
|
154
|
-
def last_entity_name
|
155
|
-
@current_context.last_context_entity_name
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
|
160
|
-
# matches argument id (integer) from used identifier (symbol)
|
161
|
-
#
|
162
|
-
# Returns: Integer as ID , or nil if not found
|
163
|
-
def match_argument_id(identifier)
|
164
|
-
matched = identifier.to_s.match(/option_([0-9]+)/)
|
165
|
-
(matched ? matched[1].to_i - 1 : nil)
|
166
|
-
end
|
167
|
-
|
168
|
-
# based on map key binding e.g. assembly_id, assembly_name we will extrace value
|
169
|
-
# from our ActiveContext
|
170
|
-
def check_context_for_element(key_mapping)
|
171
|
-
split_info = split_info(key_mapping)
|
172
|
-
entity_name = entity_name(key_mapping,split_info)
|
173
|
-
id_type = split_info[1].gsub(/!/,'') # for required elements we remove '!' required marker
|
174
|
-
context_identifier = @current_context.find_identifier(entity_name)
|
175
|
-
if context_identifier
|
176
|
-
return context_identifier.get_identifier(id_type)
|
177
|
-
else
|
178
|
-
return nil
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def entity_name(key_mapping,split_info=nil)
|
183
|
-
split_info ||= split_info(key_mapping)
|
184
|
-
split_info[0].gsub(/_/,'-') # makes sure we are using entity names with '_'
|
185
|
-
end
|
186
|
-
|
187
|
-
#
|
188
|
-
# Standardize context name since we are in domain treating :component_module as :'component-module'
|
189
|
-
# and need to be careful about these changes
|
190
|
-
#
|
191
|
-
|
192
|
-
def stand_name(name)
|
193
|
-
name.to_s.gsub('_','-').to_sym
|
194
|
-
end
|
195
|
-
|
196
|
-
def split_info(key_mapping)
|
197
|
-
key_mapping.to_s.split(/_([a-z]+!?$)/)
|
198
|
-
end
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
class ContextEntity
|
203
|
-
attr_accessor :entity
|
204
|
-
attr_accessor :name
|
205
|
-
attr_accessor :identifier
|
206
|
-
attr_accessor :alt_identifier
|
207
|
-
|
208
|
-
SHELL_SEPARATOR = '/'
|
209
|
-
|
210
|
-
def self.create_context(context_name, entity_name, context_value=nil, type_id=:id)
|
211
|
-
if context_value
|
212
|
-
if :id.eql?(type_id)
|
213
|
-
return ContextEntity.create_identifier(context_name, entity_name, context_value)
|
214
|
-
else
|
215
|
-
return ContextEntity.create_name_identifier(context_name, entity_name, context_value)
|
216
|
-
end
|
217
|
-
else
|
218
|
-
return ContextEntity.create_command(context_name, entity_name)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def is_identifier?
|
223
|
-
return !@identifier.nil?
|
224
|
-
end
|
225
|
-
|
226
|
-
def is_alt_identifier?
|
227
|
-
return !@alt_identifier.nil?
|
228
|
-
end
|
229
|
-
|
230
|
-
def is_command?
|
231
|
-
return @identifier.nil?
|
232
|
-
end
|
233
|
-
|
234
|
-
def get_identifier(type)
|
235
|
-
return (type == 'id' ? self.identifier : self.name)
|
236
|
-
end
|
237
|
-
|
238
|
-
def transform_alt_identifier_name()
|
239
|
-
@name.gsub(Client::CommandBaseThor::ALT_IDENTIFIER_SEPARATOR, SHELL_SEPARATOR)
|
240
|
-
end
|
241
|
-
|
242
|
-
private
|
243
|
-
|
244
|
-
def self.create_command(name, entity_name)
|
245
|
-
instance = ContextEntity.new
|
246
|
-
instance.name = name
|
247
|
-
instance.entity = entity_name.to_sym
|
248
|
-
return instance
|
249
|
-
end
|
250
|
-
|
251
|
-
def self.create_name_identifier(name, entity_name, value)
|
252
|
-
instance = self.create_command(name,entity_name)
|
253
|
-
instance.name = value
|
254
|
-
instance.identifier = value
|
255
|
-
instance.alt_identifier = value
|
256
|
-
return instance
|
257
|
-
end
|
258
|
-
|
259
|
-
def self.create_identifier(name, entity_name, value)
|
260
|
-
instance = self.create_command(name,entity_name)
|
261
|
-
instance.identifier = value
|
262
|
-
alt_identifier_name = name.to_s.split(Client::CommandBaseThor::ALT_IDENTIFIER_SEPARATOR)
|
263
|
-
instance.alt_identifier = alt_identifier_name.size > 1 ? alt_identifier_name.first : nil
|
264
|
-
return instance
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
class ActiveContext
|
269
|
-
|
270
|
-
# special case when we are not able to provide valid identifier but we are
|
271
|
-
# using it as such
|
272
|
-
NO_IDENTIFIER_PROVIDED = -1
|
273
|
-
|
274
|
-
# TODO: Remove accessor for debug purpose only
|
275
|
-
attr_accessor :context_list
|
276
|
-
|
277
|
-
def clone_me()
|
278
|
-
inst = ActiveContext.new
|
279
|
-
inst.context_list = @context_list.clone
|
280
|
-
return inst
|
281
|
-
end
|
282
|
-
|
283
|
-
def initialize
|
284
|
-
@context_list = []
|
285
|
-
end
|
286
|
-
|
287
|
-
def push_new_context(context_name, entity_name, context_value=nil)
|
288
|
-
@context_list << ContextEntity.create_context(context_name, entity_name, context_value)
|
289
|
-
end
|
290
|
-
def push_new_name_context(context_name, entity_name, context_value=nil)
|
291
|
-
@context_list << ContextEntity.create_context(context_name, entity_name, context_value, :name)
|
292
|
-
end
|
293
|
-
|
294
|
-
def pop_context(n)
|
295
|
-
return @context_list.pop(n)
|
296
|
-
end
|
297
|
-
|
298
|
-
def find_identifier(entity_name)
|
299
|
-
results = @context_list.select { |e| (e.is_identifier? && (e.entity == entity_name.to_sym))}
|
300
|
-
return results.first
|
301
|
-
end
|
302
|
-
|
303
|
-
def find_command(entity_name)
|
304
|
-
results = @context_list.select { |e| (e.is_command? && (e.entity == entity_name.to_sym))}
|
305
|
-
return results.first
|
306
|
-
end
|
307
|
-
|
308
|
-
def name_list()
|
309
|
-
@context_list.collect { |e| e.is_alt_identifier? ? e.transform_alt_identifier_name : e.name }
|
310
|
-
end
|
311
|
-
|
312
|
-
def name_list_simple()
|
313
|
-
@context_list.collect { |e| e.name }
|
314
|
-
end
|
315
|
-
|
316
|
-
|
317
|
-
# returns list of entities that have identifier
|
318
|
-
def commands_that_have_identifiers()
|
319
|
-
filtered_entities = @context_list.select { |e| e.is_identifier? }
|
320
|
-
return filtered_entities.collect { |e| e.entity.to_s }
|
321
|
-
end
|
322
|
-
|
323
|
-
def command_list()
|
324
|
-
filtered_entities = @context_list.select { |e| e.is_command? }
|
325
|
-
return filtered_entities.collect { |e| e.entity.to_s }
|
326
|
-
end
|
327
|
-
|
328
|
-
# returns id to be used to retrive task list form the cache based on
|
329
|
-
# current active context
|
330
|
-
def get_task_cache_id()
|
331
|
-
identifier = command_list().join('_')
|
332
|
-
return 'dtk' if identifier.empty?
|
333
|
-
if current_alt_identifier?
|
334
|
-
return "#{identifier}_#{current_alt_identifier_name()}".to_sym()
|
335
|
-
end
|
336
|
-
|
337
|
-
return current_identifier? ? "#{identifier}_wid".to_sym : identifier.to_sym
|
338
|
-
end
|
339
|
-
|
340
|
-
def full_path()
|
341
|
-
path = name_list().join('/')
|
342
|
-
path = Context.enchance_path_with_alias(path, @context_list)
|
343
|
-
|
344
|
-
return "/#{path}"
|
345
|
-
end
|
346
|
-
|
347
|
-
def clear()
|
348
|
-
@context_list.clear
|
349
|
-
end
|
350
|
-
|
351
|
-
def empty?()
|
352
|
-
return @context_list.empty?
|
353
|
-
end
|
354
|
-
|
355
|
-
def is_n_context?
|
356
|
-
@context_list.size > 2
|
357
|
-
end
|
358
|
-
|
359
|
-
def is_base_context?
|
360
|
-
@context_list.size == 1
|
361
|
-
end
|
362
|
-
|
363
|
-
def is_root_context?
|
364
|
-
@context_list.size == 0
|
365
|
-
end
|
366
|
-
|
367
|
-
def current_command?
|
368
|
-
return @context_list.empty? ? true : @context_list.last.is_command?
|
369
|
-
end
|
370
|
-
|
371
|
-
def current_identifier?
|
372
|
-
return @context_list.empty? ? false : @context_list.last.is_identifier?
|
373
|
-
end
|
374
|
-
|
375
|
-
def current_alt_identifier?
|
376
|
-
return @context_list.empty? ? false : @context_list.last.is_alt_identifier?
|
377
|
-
end
|
378
|
-
|
379
|
-
def current_alt_identifier_name
|
380
|
-
@context_list.last.alt_identifier
|
381
|
-
end
|
382
|
-
|
383
|
-
def first_command_name()
|
384
|
-
@context_list.each do |e|
|
385
|
-
return e.name if e.is_command?
|
386
|
-
end
|
387
|
-
|
388
|
-
return nil
|
389
|
-
end
|
390
|
-
|
391
|
-
def is_there_identifier_for_first_context?
|
392
|
-
@context_list.each { |e| return true if e.is_identifier? }
|
393
|
-
return false
|
394
|
-
end
|
395
|
-
|
396
|
-
def last_command_name()
|
397
|
-
@context_list.reverse.each do |e|
|
398
|
-
return e.name if e.is_command?
|
399
|
-
end
|
400
|
-
|
401
|
-
return nil
|
402
|
-
end
|
403
|
-
|
404
|
-
def last_context_entity_name()
|
405
|
-
return @context_list.empty? ? nil : @context_list.last.entity
|
406
|
-
end
|
407
|
-
|
408
|
-
def last_context_name()
|
409
|
-
return @context_list.empty? ? nil : @context_list.last.name
|
410
|
-
end
|
411
|
-
|
412
|
-
def first_context_name()
|
413
|
-
return @context_list.empty? ? nil : @context_list.first.name
|
414
|
-
end
|
415
|
-
|
416
|
-
def first_context()
|
417
|
-
return @context_list.empty? ? nil : @context_list.first
|
418
|
-
end
|
419
|
-
|
420
|
-
def last_context()
|
421
|
-
return @context_list.empty? ? nil : @context_list.last
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
class CachedTasks < Hash
|
426
|
-
end
|
427
|
-
|
428
|
-
class OverrideTasks < Hash
|
429
|
-
|
430
|
-
attr_accessor :completed_tasks
|
431
|
-
attr_accessor :always_load_list
|
432
|
-
|
433
|
-
|
434
|
-
# help_item (Thor printable task), structure:
|
435
|
-
# [0] => task defintion
|
436
|
-
# [1] => task description
|
437
|
-
# [2] => task name
|
438
|
-
|
439
|
-
# overriden_task (DTK override task), structure:
|
440
|
-
# [0] => task name
|
441
|
-
# [1] => task defintion
|
442
|
-
# [2] => task description
|
443
|
-
|
444
|
-
# using 'always load listed' to skip adding task to completed tasks e.g load utils for workspace and workspace_node
|
445
|
-
def initialize(hash=nil, always_load_listed=[])
|
446
|
-
super(hash)
|
447
|
-
@completed_tasks = []
|
448
|
-
@always_load_list = always_load_listed
|
449
|
-
self.merge!(hash)
|
450
|
-
end
|
451
|
-
|
452
|
-
# returns true if there are overrides for tasks on first two levels.
|
453
|
-
def are_there_self_override_tasks?
|
454
|
-
return (self[:all][:self] || self[:command_only][:self] || self[:identifier_only][:self])
|
455
|
-
end
|
456
|
-
|
457
|
-
def check_help_item(help_item, is_command)
|
458
|
-
command_tasks, identifier_tasks = get_all_tasks(:self)
|
459
|
-
found = []
|
460
|
-
|
461
|
-
if is_command
|
462
|
-
found = command_tasks.select { |o_task| o_task[0].eql?(help_item[2]) }
|
463
|
-
else
|
464
|
-
found = identifier_tasks.select { |o_task| o_task[0].eql?(help_item[2]) }
|
465
|
-
end
|
466
|
-
|
467
|
-
# if we find self overriden task we remove it
|
468
|
-
# [found.first[1],found.first[2],found.first[0]] => we convert from o_task structure to thor help structure
|
469
|
-
return found.empty? ? help_item : [found.first[1],found.first[2],found.first[0]]
|
470
|
-
end
|
471
|
-
|
472
|
-
# returns 2 arrays one for commands and next one for identifiers
|
473
|
-
def get_all_tasks(child_name)
|
474
|
-
command_o_tasks, identifier_o_tasks = [], []
|
475
|
-
command_o_tasks = (self[:all][child_name]||[]) + (self[:command_only][child_name]||[])
|
476
|
-
identifier_o_tasks = (self[:all][child_name]||[]) + (self[:identifier_only][child_name]||[])
|
477
|
-
return command_o_tasks, identifier_o_tasks
|
478
|
-
end
|
479
|
-
|
480
|
-
def is_completed?(child_name)
|
481
|
-
# do not add task to completed if explicitly said to always load that task
|
482
|
-
return false if @always_load_list.include?(child_name)
|
483
|
-
@completed_tasks.include?(child_name)
|
484
|
-
end
|
485
|
-
|
486
|
-
def add_to_completed(child_name)
|
487
|
-
@completed_tasks << child_name
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
|
-
end
|
492
|
-
end
|