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.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/bin/dtk +5 -1
  3. data/lib/auxiliary.rb +0 -1
  4. data/lib/commands/common/thor/assembly_workspace.rb +20 -1
  5. data/lib/commands/common/thor/inventory_parser.rb +1 -1
  6. data/lib/commands/common/thor/module/import.rb +41 -106
  7. data/lib/commands/common/thor/module.rb +13 -226
  8. data/lib/commands/common/thor/poller.rb +48 -0
  9. data/lib/commands/common/thor/puppet_forge.rb +7 -1
  10. data/lib/commands/common/thor/purge_clone.rb +2 -1
  11. data/lib/commands/common/thor/task_status.rb +15 -14
  12. data/lib/commands/common/thor/test_action_agent.rb +39 -0
  13. data/lib/commands/thor/component_module.rb +2 -2
  14. data/lib/commands/thor/node.rb +55 -14
  15. data/lib/commands/thor/node_group.rb +2 -26
  16. data/lib/commands/thor/service.rb +31 -11
  17. data/lib/commands/thor/service_module.rb +3 -1
  18. data/lib/commands/thor/workspace.rb +13 -3
  19. data/lib/core.rb +16 -6
  20. data/lib/domain/git_adapter.rb +0 -3
  21. data/lib/domain/response.rb +25 -13
  22. data/lib/dtk-client/version.rb +1 -1
  23. data/lib/parser/adapters/thor.rb +8 -5
  24. data/lib/shell/context.rb +8 -19
  25. data/lib/shell/domain/active_context.rb +169 -0
  26. data/lib/shell/domain/context_entity.rb +72 -0
  27. data/lib/shell/domain/context_params.rb +202 -0
  28. data/lib/shell/domain/override_tasks.rb +71 -0
  29. data/lib/shell/domain/shadow_entity.rb +59 -0
  30. data/lib/shell/help_monkey_patch.rb +76 -71
  31. data/lib/shell/message_queue.rb +2 -0
  32. data/lib/shell/status_monitor.rb +5 -3
  33. data/lib/shell.rb +4 -2
  34. data/lib/util/dtk_puppet.rb +8 -6
  35. data/lib/util/os_util.rb +5 -1
  36. data/lib/view_processor/table_print.rb +67 -12
  37. data/spec/lib/spec_thor.rb +5 -2
  38. metadata +9 -3
  39. 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