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/domain/response.rb
CHANGED
@@ -52,17 +52,23 @@ module DTK
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def get_label_for_column_name(column, type)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
55
|
+
if type.eql?('node')
|
56
|
+
mappings = {
|
57
|
+
column => column
|
58
|
+
}
|
59
|
+
else
|
60
|
+
mappings = {
|
61
|
+
"#{type}_id:" => "ID:",
|
62
|
+
"#{type}_name:" => "NAME:",
|
63
|
+
"node_type:" => "TYPE:",
|
64
|
+
"instance_id:" => "INSTANCE ID:",
|
65
|
+
"size:" => "SIZE:",
|
66
|
+
"os_type:" => "OS:",
|
67
|
+
"op_status:" => "OP STATUS:",
|
68
|
+
"dns_name:" => "DNS NAME:",
|
69
|
+
"target:" => "TARGET:"
|
70
|
+
}
|
71
|
+
end
|
66
72
|
|
67
73
|
mappings[column]
|
68
74
|
end
|
@@ -73,7 +79,7 @@ module DTK
|
|
73
79
|
if type.eql?("component")
|
74
80
|
info_list = ["component_name","component_id","basic_type","description"]
|
75
81
|
else
|
76
|
-
info_list = ["node_id", "node_name","os_type", "instance_id", "
|
82
|
+
info_list = ["type", "node_id", "node_name","os_type", "instance_id", "admin_op_status", "size", "target", "dns_name", "image_id", "ec2_public_address", "privete_dns_name", "keypair", "security_groups", "security_group", "security_group_set"]
|
77
83
|
end
|
78
84
|
|
79
85
|
columns = []
|
@@ -91,7 +97,13 @@ module DTK
|
|
91
97
|
end
|
92
98
|
end
|
93
99
|
|
94
|
-
|
100
|
+
if type.eql?('node')
|
101
|
+
# move target from first place
|
102
|
+
columns.rotate!
|
103
|
+
else
|
104
|
+
columns.sort!()
|
105
|
+
end
|
106
|
+
|
95
107
|
columns.each do |column|
|
96
108
|
STDOUT << column
|
97
109
|
end
|
data/lib/dtk-client/version.rb
CHANGED
data/lib/parser/adapters/thor.rb
CHANGED
@@ -10,6 +10,7 @@ dtk_require("../../util/console")
|
|
10
10
|
dtk_require_common_commands('thor/task_status')
|
11
11
|
dtk_require_from_base("command_helper")
|
12
12
|
dtk_require("../../context_router")
|
13
|
+
dtk_require_common_commands('thor/poller')
|
13
14
|
|
14
15
|
module DTK
|
15
16
|
module Client
|
@@ -17,10 +18,12 @@ module DTK
|
|
17
18
|
dtk_nested_require('thor','common_option_defs')
|
18
19
|
|
19
20
|
include CommandBase
|
21
|
+
include CommandHelperMixin
|
22
|
+
include Poller
|
23
|
+
|
20
24
|
extend CommandBase
|
21
25
|
extend TaskStatusMixin
|
22
26
|
extend Console
|
23
|
-
include CommandHelperMixin
|
24
27
|
extend CommonOptionDefs::ClassMixin
|
25
28
|
|
26
29
|
@@cached_response = {}
|
@@ -74,7 +77,7 @@ module DTK
|
|
74
77
|
if action['wait_for_complete']
|
75
78
|
entity_id, entity_type = action['wait_for_complete']['id'].to_s, action['wait_for_complete']['type']
|
76
79
|
puts "Waiting for task to complete ..."
|
77
|
-
task_status_aux(entity_id,entity_type
|
80
|
+
task_status_aux(entity_id,entity_type,:wait => true)
|
78
81
|
end
|
79
82
|
else
|
80
83
|
# validation action are being skipped
|
@@ -326,7 +329,7 @@ module DTK
|
|
326
329
|
unless response['data'].nil?
|
327
330
|
identifiers = []
|
328
331
|
response['data'].each do |element|
|
329
|
-
identifiers << { :name => element['display_name'], :identifier => element['id'] }
|
332
|
+
identifiers << { :name => element['display_name'], :identifier => element['id'], :shadow_entity => element['dtk_client_type'] }
|
330
333
|
end
|
331
334
|
return identifiers
|
332
335
|
end
|
@@ -403,7 +406,7 @@ module DTK
|
|
403
406
|
|
404
407
|
match = nil
|
405
408
|
response = self.class.get_cached_response(entity_type,list_command_path,subtype)
|
406
|
-
if response.ok? and response['data']
|
409
|
+
if response and response.ok? and response['data']
|
407
410
|
match = response['data'].find{|entity|entity_id == entity['id']}
|
408
411
|
end
|
409
412
|
unless match
|
@@ -428,7 +431,7 @@ module DTK
|
|
428
431
|
|
429
432
|
# removes nil values
|
430
433
|
def post_body(hash)
|
431
|
-
hash.inject(Hash.new){|h,(k,v)|v.nil? ? h : h.merge(k => v)}
|
434
|
+
hash.inject(Hash.new){|h,(k,v)|v.nil? ? h : h.merge(k => v)}
|
432
435
|
end
|
433
436
|
|
434
437
|
# User input prompt
|
data/lib/shell/context.rb
CHANGED
@@ -351,7 +351,7 @@ module DTK
|
|
351
351
|
break
|
352
352
|
end
|
353
353
|
|
354
|
-
active_context_copy.push_new_context(context_hash_data[:name], command, context_hash_data[:identifier]) if ((i+1) >= ac_size)
|
354
|
+
active_context_copy.push_new_context(context_hash_data[:name], command, context_hash_data[:identifier], context_hash_data[:shadow_entity]) if ((i+1) >= ac_size)
|
355
355
|
end
|
356
356
|
end
|
357
357
|
|
@@ -512,8 +512,12 @@ module DTK
|
|
512
512
|
# so getting context for 'public' will not work and we use than library
|
513
513
|
command_name = root? ? 'dtk' : @active_context.last_command_name
|
514
514
|
|
515
|
-
|
516
|
-
|
515
|
+
if @active_context.last_context_is_shadow_entity?
|
516
|
+
@current = ShadowEntity.resolve_tasks(@active_context.last_context)
|
517
|
+
else
|
518
|
+
# if there is no new context (current) we use old one
|
519
|
+
@current = current_context_task_names() || @current
|
520
|
+
end
|
517
521
|
|
518
522
|
client_commands = CLIENT_COMMANDS
|
519
523
|
client_commands.concat(DEV_COMMANDS) if DTK::Configuration.get(:development_mode)
|
@@ -530,6 +534,7 @@ module DTK
|
|
530
534
|
command_name_list = command_context ? command_context.collect { |e| e[:name] } : []
|
531
535
|
@context_commands.concat(command_name_list) if current_command?
|
532
536
|
|
537
|
+
|
533
538
|
# logic behind context loading
|
534
539
|
#Readline.completer_word_break_characters=" "
|
535
540
|
Readline.completion_proc = proc { |input| dynamic_autocomplete_context(input, Readline.respond_to?("line_buffer") ? Readline.line_buffer : [])}
|
@@ -798,22 +803,6 @@ module DTK
|
|
798
803
|
candidates
|
799
804
|
end
|
800
805
|
|
801
|
-
# changes command and argument if argument is plural of one of
|
802
|
-
# the possible commands on tier1 e.g. libraries, assemblies
|
803
|
-
# return 2 values cmd, args
|
804
|
-
def reverse_commands(cmd, args)
|
805
|
-
# iterates trough current context available commands
|
806
|
-
@current.each do |available_commands|
|
807
|
-
# singulirazes command, e.g. libraries => library
|
808
|
-
command_singular=args.first.singularize
|
809
|
-
if available_commands.eql?(command_singular)
|
810
|
-
cmd, args = command_singular, [cmd]
|
811
|
-
end
|
812
|
-
end
|
813
|
-
|
814
|
-
return cmd, args
|
815
|
-
end
|
816
|
-
|
817
806
|
def get_dtk_command_parameters(entity_name, args)
|
818
807
|
method_name, entity_name_id = nil, nil
|
819
808
|
context_params = ContextParams.new
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module DTK::Shell
|
2
|
+
class ActiveContext
|
3
|
+
|
4
|
+
# special case when we are not able to provide valid identifier but we are
|
5
|
+
# using it as such
|
6
|
+
NO_IDENTIFIER_PROVIDED = -1
|
7
|
+
|
8
|
+
# TODO: Remove accessor for debug purpose only
|
9
|
+
attr_accessor :context_list
|
10
|
+
|
11
|
+
def clone_me()
|
12
|
+
inst = ActiveContext.new
|
13
|
+
inst.context_list = @context_list.clone
|
14
|
+
return inst
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@context_list = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def push_new_context(context_name, entity_name, context_value=nil, shadow_entity=nil)
|
22
|
+
@context_list << ContextEntity.create_context(context_name, entity_name, context_value, :id, shadow_entity)
|
23
|
+
end
|
24
|
+
|
25
|
+
def push_new_name_context(context_name, entity_name, context_value=nil)
|
26
|
+
@context_list << ContextEntity.create_context(context_name, entity_name, context_value, :name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def pop_context(n)
|
30
|
+
return @context_list.pop(n)
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_identifier(entity_name)
|
34
|
+
results = @context_list.select { |e| (e.is_identifier? && (e.entity == entity_name.to_sym))}
|
35
|
+
return results.first
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_command(entity_name)
|
39
|
+
results = @context_list.select { |e| (e.is_command? && (e.entity == entity_name.to_sym))}
|
40
|
+
return results.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def name_list()
|
44
|
+
@context_list.collect { |e| e.is_alt_identifier? ? e.transform_alt_identifier_name : e.name }
|
45
|
+
end
|
46
|
+
|
47
|
+
def name_list_simple()
|
48
|
+
@context_list.collect { |e| e.name }
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# returns list of entities that have identifier
|
53
|
+
def commands_that_have_identifiers()
|
54
|
+
filtered_entities = @context_list.select { |e| e.is_identifier? }
|
55
|
+
return filtered_entities.collect { |e| e.entity.to_s }
|
56
|
+
end
|
57
|
+
|
58
|
+
def command_list()
|
59
|
+
filtered_entities = @context_list.select { |e| e.is_command? }
|
60
|
+
return filtered_entities.collect { |e| e.entity.to_s }
|
61
|
+
end
|
62
|
+
|
63
|
+
# returns id to be used to retrive task list form the cache based on
|
64
|
+
# current active context
|
65
|
+
def get_task_cache_id()
|
66
|
+
identifier = command_list().join('_')
|
67
|
+
return 'dtk' if identifier.empty?
|
68
|
+
if current_alt_identifier?
|
69
|
+
return "#{identifier}_#{current_alt_identifier_name()}".to_sym()
|
70
|
+
end
|
71
|
+
|
72
|
+
return current_identifier? ? "#{identifier}_wid".to_sym : identifier.to_sym
|
73
|
+
end
|
74
|
+
|
75
|
+
def full_path()
|
76
|
+
path = name_list().join('/')
|
77
|
+
path = Context.enchance_path_with_alias(path, @context_list)
|
78
|
+
|
79
|
+
return "/#{path}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def clear()
|
83
|
+
@context_list.clear
|
84
|
+
end
|
85
|
+
|
86
|
+
def empty?()
|
87
|
+
return @context_list.empty?
|
88
|
+
end
|
89
|
+
|
90
|
+
def is_n_context?
|
91
|
+
@context_list.size > 2
|
92
|
+
end
|
93
|
+
|
94
|
+
def is_base_context?
|
95
|
+
@context_list.size == 1
|
96
|
+
end
|
97
|
+
|
98
|
+
def is_root_context?
|
99
|
+
@context_list.size == 0
|
100
|
+
end
|
101
|
+
|
102
|
+
def current_command?
|
103
|
+
return @context_list.empty? ? true : @context_list.last.is_command?
|
104
|
+
end
|
105
|
+
|
106
|
+
def current_identifier?
|
107
|
+
return @context_list.empty? ? false : @context_list.last.is_identifier?
|
108
|
+
end
|
109
|
+
|
110
|
+
def current_alt_identifier?
|
111
|
+
return @context_list.empty? ? false : @context_list.last.is_alt_identifier?
|
112
|
+
end
|
113
|
+
|
114
|
+
def current_alt_identifier_name
|
115
|
+
@context_list.last.alt_identifier
|
116
|
+
end
|
117
|
+
|
118
|
+
def first_command_name()
|
119
|
+
@context_list.each do |e|
|
120
|
+
return e.name if e.is_command?
|
121
|
+
end
|
122
|
+
|
123
|
+
return nil
|
124
|
+
end
|
125
|
+
|
126
|
+
def is_there_identifier_for_first_context?
|
127
|
+
@context_list.each { |e| return true if e.is_identifier? }
|
128
|
+
return false
|
129
|
+
end
|
130
|
+
|
131
|
+
def last_command_name()
|
132
|
+
@context_list.reverse.each do |e|
|
133
|
+
return e.name if e.is_command?
|
134
|
+
end
|
135
|
+
|
136
|
+
return nil
|
137
|
+
end
|
138
|
+
|
139
|
+
def last_context_entity_name()
|
140
|
+
return @context_list.empty? ? nil : @context_list.last.entity
|
141
|
+
end
|
142
|
+
|
143
|
+
def last_context_name()
|
144
|
+
return @context_list.empty? ? nil : @context_list.last.name
|
145
|
+
end
|
146
|
+
|
147
|
+
def first_context_name()
|
148
|
+
return @context_list.empty? ? nil : @context_list.first.name
|
149
|
+
end
|
150
|
+
|
151
|
+
def first_context()
|
152
|
+
return @context_list.empty? ? nil : @context_list.first
|
153
|
+
end
|
154
|
+
|
155
|
+
def last_context()
|
156
|
+
return @context_list.empty? ? nil : @context_list.last
|
157
|
+
end
|
158
|
+
|
159
|
+
def last_context_is_shadow_entity?
|
160
|
+
return false if @context_list.empty?
|
161
|
+
!!last_context().shadow_entity
|
162
|
+
end
|
163
|
+
|
164
|
+
def shadow_entity()
|
165
|
+
return if @context_list.empty?
|
166
|
+
last_context().shadow_entity
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module DTK::Shell
|
2
|
+
class ContextEntity
|
3
|
+
attr_accessor :entity
|
4
|
+
attr_accessor :name
|
5
|
+
attr_accessor :identifier
|
6
|
+
attr_accessor :alt_identifier
|
7
|
+
attr_accessor :shadow_entity
|
8
|
+
|
9
|
+
SHELL_SEPARATOR = '/'
|
10
|
+
|
11
|
+
def self.create_context(context_name, entity_name, context_value=nil, type_id=:id, shadow_entity=nil)
|
12
|
+
if context_value
|
13
|
+
if :id.eql?(type_id)
|
14
|
+
return ContextEntity.create_identifier(context_name, entity_name, context_value, shadow_entity)
|
15
|
+
else
|
16
|
+
return ContextEntity.create_name_identifier(context_name, entity_name, context_value, shadow_entity)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
return ContextEntity.create_command(context_name, entity_name, shadow_entity)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_identifier?
|
24
|
+
return !@identifier.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_alt_identifier?
|
28
|
+
return !@alt_identifier.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_command?
|
32
|
+
return @identifier.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_identifier(type)
|
36
|
+
return (type == 'id' ? self.identifier : self.name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def transform_alt_identifier_name()
|
40
|
+
@name.gsub(::DTK::Client::CommandBaseThor::ALT_IDENTIFIER_SEPARATOR, SHELL_SEPARATOR)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def self.create_command(name, entity_name, shadow_entity=nil)
|
46
|
+
instance = ContextEntity.new
|
47
|
+
instance.name = name
|
48
|
+
instance.entity = entity_name.to_sym
|
49
|
+
instance.shadow_entity = shadow_entity
|
50
|
+
return instance
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.create_name_identifier(name, entity_name, value, shadow_entity=nil)
|
54
|
+
instance = self.create_command(name,entity_name)
|
55
|
+
instance.name = value
|
56
|
+
instance.identifier = value
|
57
|
+
instance.alt_identifier = value
|
58
|
+
instance.shadow_entity = shadow_entity
|
59
|
+
|
60
|
+
return instance
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.create_identifier(name, entity_name, value, shadow_entity=nil)
|
64
|
+
instance = self.create_command(name,entity_name)
|
65
|
+
instance.identifier = value
|
66
|
+
alt_identifier_name = name.to_s.split(::DTK::Client::CommandBaseThor::ALT_IDENTIFIER_SEPARATOR)
|
67
|
+
instance.alt_identifier = alt_identifier_name.size > 1 ? alt_identifier_name.first : nil
|
68
|
+
instance.shadow_entity = shadow_entity
|
69
|
+
return instance
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
module DTK::Shell
|
2
|
+
class ContextParams
|
3
|
+
|
4
|
+
attr_accessor :current_context
|
5
|
+
attr_accessor :method_arguments
|
6
|
+
|
7
|
+
def initialize(override_method_arguments = [])
|
8
|
+
@current_context = ActiveContext.new
|
9
|
+
@method_arguments = override_method_arguments
|
10
|
+
@thor_options = Hash.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_context_to_params(context_name, entity_name, context_value = nil)
|
14
|
+
@current_context.push_new_context(context_name, stand_name(entity_name), context_value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_context_name_to_params(context_name, entity_name, context_value = nil)
|
18
|
+
@current_context.push_new_name_context(context_name, stand_name(entity_name), context_value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def forward_options(options)
|
22
|
+
@thor_options = options
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_forwarded_options()
|
26
|
+
@thor_options
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_forwarded_thor_option(option_key)
|
30
|
+
return @thor_options ? @thor_options[option_key] : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def override_method_argument!(key, value)
|
34
|
+
id = match_argument_id(key)
|
35
|
+
raise DTK::Client::DtkImplementationError, "Wrong identifier used '#{key}', ID not matched!" unless id
|
36
|
+
@method_arguments[id] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
# can be class methods but no need, since we have this instance available in each method
|
40
|
+
def retrieve_thor_options(mapping, options)
|
41
|
+
results = []
|
42
|
+
errors = []
|
43
|
+
|
44
|
+
mapping.each do |key|
|
45
|
+
required = key.to_s.match(/.+!$/)
|
46
|
+
thor_key = key.to_s.gsub('!','')
|
47
|
+
|
48
|
+
results << element = options[thor_key]
|
49
|
+
|
50
|
+
if required && element.nil?
|
51
|
+
errors << thor_key
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
unless errors.empty?
|
56
|
+
raise DTK::Client::DtkValidationError.new("Missing required option#{errors.size > 1 ? 's' : ''}: #{errors.join(', ')}", true)
|
57
|
+
end
|
58
|
+
|
59
|
+
return ((results.size == 1) ? results.first : results)
|
60
|
+
end
|
61
|
+
|
62
|
+
def retrieve_arguments(mapping, method_info = [])
|
63
|
+
results = []
|
64
|
+
errors = []
|
65
|
+
|
66
|
+
# using context_name when have array as key_mapping [:assembly_id, :workspace_id]
|
67
|
+
# to determine which context is used
|
68
|
+
context_name = method_info.first.split('-').first unless method_info.empty?
|
69
|
+
|
70
|
+
mapping.each do |key_mapping|
|
71
|
+
|
72
|
+
is_array = key_mapping.is_a?(Array)
|
73
|
+
|
74
|
+
selected_key = is_array ? key_mapping.first : key_mapping
|
75
|
+
|
76
|
+
required = selected_key.to_s.match(/.+!$/)
|
77
|
+
|
78
|
+
element = nil
|
79
|
+
matched = selected_key.to_s.match(/option_([0-9]+)/)
|
80
|
+
if matched
|
81
|
+
id = matched[1].to_i - 1
|
82
|
+
element = @method_arguments[id]
|
83
|
+
|
84
|
+
# used if last parameter has more than one word
|
85
|
+
# e.g. set-attribute attr_name "some value" (thor separates 'some value' as two parameters but we need it as one)
|
86
|
+
if(mapping.last.to_s.eql?(key_mapping.to_s))
|
87
|
+
new_id = id+1
|
88
|
+
while @method_arguments[new_id] do
|
89
|
+
element << " #{@method_arguments[new_id]}"
|
90
|
+
new_id += 1;
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
unless method_info.empty?
|
95
|
+
unless element
|
96
|
+
errors << method_info[id] if required
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
else
|
101
|
+
# More complex split regex for extracting entitiy name from mapping due to complex context names
|
102
|
+
# i.e. assembly-template will have assembly_template_id mapping
|
103
|
+
element = check_context_for_element(selected_key)
|
104
|
+
|
105
|
+
# if we are dealing with array we need to check rest of the keys since it is OR
|
106
|
+
# approach if first element not found take second
|
107
|
+
if element.nil? && is_array
|
108
|
+
key_mapping[1..-1].each do |alternative_key|
|
109
|
+
element = check_context_for_element(alternative_key)
|
110
|
+
break if element
|
111
|
+
if context_name
|
112
|
+
if alternative_key.to_s.include?(context_name.downcase)
|
113
|
+
required = alternative_key.to_s.match(/.+!$/)
|
114
|
+
selected_key = alternative_key
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
unless element
|
121
|
+
errors << "#{entity_name(selected_key).upcase} ID/NAME" if required
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
results << element
|
126
|
+
end
|
127
|
+
|
128
|
+
unless errors.empty?
|
129
|
+
raise DTK::Client::DtkValidationError.new("Missing required argument#{errors.size > 1 ? 's' : ''}: #{errors.join(', ')}", true)
|
130
|
+
end
|
131
|
+
|
132
|
+
return ((results.size == 1) ? results.first : results)
|
133
|
+
end
|
134
|
+
|
135
|
+
def is_last_command_eql_to?(command_name)
|
136
|
+
return @current_context.last_command_name() == command_name.to_s
|
137
|
+
end
|
138
|
+
|
139
|
+
def is_there_identifier?(entity_name)
|
140
|
+
return @current_context.find_identifier(entity_name) != nil
|
141
|
+
end
|
142
|
+
|
143
|
+
def is_there_command?(entity_name)
|
144
|
+
return @current_context.find_command(entity_name) != nil
|
145
|
+
end
|
146
|
+
def current_command?
|
147
|
+
return @current_context.current_command?
|
148
|
+
end
|
149
|
+
def root_command_name
|
150
|
+
@current_context.first_command_name
|
151
|
+
end
|
152
|
+
def last_entity_name
|
153
|
+
@current_context.last_context_entity_name
|
154
|
+
end
|
155
|
+
def shadow_entity_name()
|
156
|
+
@current_context.shadow_entity()
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
# matches argument id (integer) from used identifier (symbol)
|
162
|
+
#
|
163
|
+
# Returns: Integer as ID , or nil if not found
|
164
|
+
def match_argument_id(identifier)
|
165
|
+
matched = identifier.to_s.match(/option_([0-9]+)/)
|
166
|
+
(matched ? matched[1].to_i - 1 : nil)
|
167
|
+
end
|
168
|
+
|
169
|
+
# based on map key binding e.g. assembly_id, assembly_name we will extrace value
|
170
|
+
# from our ActiveContext
|
171
|
+
def check_context_for_element(key_mapping)
|
172
|
+
split_info = split_info(key_mapping)
|
173
|
+
entity_name = entity_name(key_mapping,split_info)
|
174
|
+
id_type = split_info[1].gsub(/!/,'') # for required elements we remove '!' required marker
|
175
|
+
context_identifier = @current_context.find_identifier(entity_name)
|
176
|
+
if context_identifier
|
177
|
+
return context_identifier.get_identifier(id_type)
|
178
|
+
else
|
179
|
+
return nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def entity_name(key_mapping,split_info=nil)
|
184
|
+
split_info ||= split_info(key_mapping)
|
185
|
+
split_info[0].gsub(/_/,'-') # makes sure we are using entity names with '_'
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# Standardize context name since we are in domain treating :component_module as :'component-module'
|
190
|
+
# and need to be careful about these changes
|
191
|
+
#
|
192
|
+
|
193
|
+
def stand_name(name)
|
194
|
+
name.to_s.gsub('_','-').to_sym
|
195
|
+
end
|
196
|
+
|
197
|
+
def split_info(key_mapping)
|
198
|
+
key_mapping.to_s.split(/_([a-z]+!?$)/)
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module DTK
|
2
|
+
module Shell
|
3
|
+
|
4
|
+
class CachedTasks < Hash
|
5
|
+
end
|
6
|
+
|
7
|
+
class OverrideTasks < Hash
|
8
|
+
|
9
|
+
attr_accessor :completed_tasks
|
10
|
+
attr_accessor :always_load_list
|
11
|
+
|
12
|
+
|
13
|
+
# help_item (Thor printable task), structure:
|
14
|
+
# [0] => task defintion
|
15
|
+
# [1] => task description
|
16
|
+
# [2] => task name
|
17
|
+
|
18
|
+
# overriden_task (DTK override task), structure:
|
19
|
+
# [0] => task name
|
20
|
+
# [1] => task defintion
|
21
|
+
# [2] => task description
|
22
|
+
|
23
|
+
# using 'always load listed' to skip adding task to completed tasks e.g load utils for workspace and workspace_node
|
24
|
+
def initialize(hash=nil, always_load_listed=[])
|
25
|
+
super(hash)
|
26
|
+
@completed_tasks = []
|
27
|
+
@always_load_list = always_load_listed
|
28
|
+
self.merge!(hash)
|
29
|
+
end
|
30
|
+
|
31
|
+
# returns true if there are overrides for tasks on first two levels.
|
32
|
+
def are_there_self_override_tasks?
|
33
|
+
return (self[:all][:self] || self[:command_only][:self] || self[:identifier_only][:self])
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_help_item(help_item, is_command)
|
37
|
+
command_tasks, identifier_tasks = get_all_tasks(:self)
|
38
|
+
found = []
|
39
|
+
|
40
|
+
if is_command
|
41
|
+
found = command_tasks.select { |o_task| o_task[0].eql?(help_item[2]) }
|
42
|
+
else
|
43
|
+
found = identifier_tasks.select { |o_task| o_task[0].eql?(help_item[2]) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# if we find self overriden task we remove it
|
47
|
+
# [found.first[1],found.first[2],found.first[0]] => we convert from o_task structure to thor help structure
|
48
|
+
return found.empty? ? help_item : [found.first[1],found.first[2],found.first[0]]
|
49
|
+
end
|
50
|
+
|
51
|
+
# returns 2 arrays one for commands and next one for identifiers
|
52
|
+
def get_all_tasks(child_name)
|
53
|
+
command_o_tasks, identifier_o_tasks = [], []
|
54
|
+
command_o_tasks = (self[:all][child_name]||[]) + (self[:command_only][child_name]||[])
|
55
|
+
identifier_o_tasks = (self[:all][child_name]||[]) + (self[:identifier_only][child_name]||[])
|
56
|
+
return command_o_tasks, identifier_o_tasks
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_completed?(child_name)
|
60
|
+
# do not add task to completed if explicitly said to always load that task
|
61
|
+
return false if @always_load_list.include?(child_name)
|
62
|
+
@completed_tasks.include?(child_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_to_completed(child_name)
|
66
|
+
@completed_tasks << child_name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|