dtk-client 0.5.17 → 0.5.18

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 (35) hide show
  1. checksums.yaml +8 -8
  2. data/lib/command_helpers/git_repo.rb +82 -48
  3. data/lib/command_helpers/service_importer.rb +26 -17
  4. data/lib/command_helpers/test_module_creator.rb +6 -5
  5. data/lib/commands/common/thor/access_control.rb +5 -4
  6. data/lib/commands/common/thor/assembly_template.rb +75 -0
  7. data/lib/commands/common/thor/assembly_workspace.rb +86 -71
  8. data/lib/commands/common/thor/clone.rb +9 -7
  9. data/lib/commands/common/thor/common.rb +17 -10
  10. data/lib/commands/common/thor/edit.rb +65 -6
  11. data/lib/commands/common/thor/list_diffs.rb +4 -3
  12. data/lib/commands/common/thor/module.rb +86 -89
  13. data/lib/commands/common/thor/pull_clone_changes.rb +3 -2
  14. data/lib/commands/common/thor/pull_from_remote.rb +9 -5
  15. data/lib/commands/common/thor/purge_clone.rb +2 -2
  16. data/lib/commands/common/thor/push_clone_changes.rb +39 -16
  17. data/lib/commands/common/thor/push_to_remote.rb +3 -3
  18. data/lib/commands/thor/account.rb +16 -4
  19. data/lib/commands/thor/assembly.rb +66 -89
  20. data/lib/commands/thor/component_module.rb +40 -24
  21. data/lib/commands/thor/node.rb +7 -0
  22. data/lib/commands/thor/provider.rb +45 -23
  23. data/lib/commands/thor/service.rb +4 -7
  24. data/lib/commands/thor/service_module.rb +45 -20
  25. data/lib/commands/thor/test_module.rb +36 -22
  26. data/lib/commands/thor/workspace.rb +6 -6
  27. data/lib/core.rb +18 -17
  28. data/lib/domain/git_adapter.rb +30 -9
  29. data/lib/dtk-client/version.rb +1 -1
  30. data/lib/parser/adapters/thor.rb +47 -25
  31. data/lib/shell/context.rb +10 -2
  32. data/lib/shell.rb +18 -12
  33. data/lib/util/module_util.rb +41 -0
  34. data/lib/util/os_util.rb +25 -7
  35. metadata +4 -2
@@ -31,7 +31,7 @@ module DTK
31
31
 
32
32
  # thor command specific constants
33
33
  ALT_IDENTIFIER_SEPARATOR = ':::'
34
-
34
+
35
35
  def initialize(args, opts, config)
36
36
  @conn = config[:conn]
37
37
  super
@@ -41,7 +41,7 @@ module DTK
41
41
  @@shell_execution = shell_execution
42
42
 
43
43
  if method_name == 'help'
44
- ret = start([method_name] + context_params.method_arguments,:conn => conn)
44
+ ret = start([method_name] + context_params.method_arguments,:conn => conn)
45
45
  else
46
46
  ret = start([method_name, context_params] + (thor_options||[]),:conn => conn)
47
47
  end
@@ -103,15 +103,15 @@ module DTK
103
103
  subtype ||= {}
104
104
  current_ts = Time.now.to_i
105
105
  cache_id = (subtype.empty? ? :response : generate_cached_id(subtype))
106
-
106
+
107
107
  # if @@cache_response is empty return true if not than return time difference between
108
108
  # current_ts and ts stored in cache
109
- time_difference = @@cached_response[entity_name].nil? ? true : ((current_ts - @@cached_response[entity_name][:ts]) > TIME_DIFF)
109
+ time_difference = @@cached_response[entity_name].nil? ? true : ((current_ts - @@cached_response[entity_name][:ts]) > TIME_DIFF)
110
110
 
111
111
  if (@@cached_response[entity_name])
112
112
  time_difference = true if @@cached_response[entity_name][cache_id].nil?
113
113
  end
114
-
114
+
115
115
  if (time_difference || @@invalidate_map.include?(entity_name))
116
116
  response = post rest_url(url), subtype
117
117
 
@@ -149,8 +149,8 @@ module DTK
149
149
  # symbols don't have a <=> comparison operator in ruby 1.8.7
150
150
  subtype.map do |key,value|
151
151
  values += value.to_s
152
- end
153
-
152
+ end
153
+
154
154
  Digest::SHA1.hexdigest(values)
155
155
  end
156
156
 
@@ -232,7 +232,7 @@ module DTK
232
232
  alternate_identifiers.each do |a_provider|
233
233
  if matched_alt_identifiers_data = task[1].usage.match(/\[?#{a_provider}.?(NAME\/ID|ID\/NAME)\]?/)
234
234
  command_alt_sym = "#{command}_#{a_provider}".downcase.to_sym
235
- cached_tasks[command_alt_sym] = cached_tasks.fetch(command_alt_sym,[])
235
+ cached_tasks[command_alt_sym] = cached_tasks.fetch(command_alt_sym,[])
236
236
  cached_tasks[command_alt_sym] << task_name
237
237
  # when found break
238
238
  break
@@ -254,7 +254,7 @@ module DTK
254
254
  # if there are '[' it means it is optinal identifiers so it is tier 1 and tier 2 task
255
255
  cached_tasks[command_sym] << task_name if matched_data[0].include?('[')
256
256
  end
257
-
257
+
258
258
  # n-level matching
259
259
  all_children.each do |child|
260
260
  current_children = []
@@ -268,7 +268,7 @@ module DTK
268
268
  # n-context matching
269
269
  matched_data = task[1].usage.match(/^\[?#{c.to_s.upcase}.?(NAME\/ID|ID\/NAME|ID|NAME)(\-?PATTERN)?\]?/)
270
270
  if matched_data
271
- cached_tasks[child_id_sym] = cached_tasks.fetch(child_id_sym,[]) << task_name
271
+ cached_tasks[child_id_sym] = cached_tasks.fetch(child_id_sym,[]) << task_name
272
272
  end
273
273
 
274
274
  # override method list, we add these methods only once
@@ -290,7 +290,7 @@ module DTK
290
290
  end
291
291
  end
292
292
  end
293
-
293
+
294
294
  # there is always help, and in all cases this is exception to the rule
295
295
  cached_tasks[command_id_sym] << 'help'
296
296
 
@@ -303,18 +303,18 @@ module DTK
303
303
 
304
304
  context_list = self.get_identifiers(conn, context_params)
305
305
  results = context_list.select { |e| e[:name].eql?(value) || e[:identifier].eql?(value.to_i)}
306
-
306
+
307
307
  return results.empty? ? nil : results.first
308
308
  end
309
309
 
310
310
  def self.get_identifiers(conn, context_params)
311
311
  @conn = conn if @conn.nil?
312
-
312
+
313
313
  # we force raw output
314
314
  # options = Thor::CoreExt::HashWithIndifferentAccess.new({'list' => true})
315
315
 
316
316
  3.downto(1) do
317
- # get list data from one of the methods
317
+ # get list data from one of the methods
318
318
  if respond_to?(:validation_list)
319
319
  response = validation_list(context_params)
320
320
  else
@@ -324,12 +324,12 @@ module DTK
324
324
 
325
325
  unless (response.nil? || response.empty?)
326
326
  unless response['data'].nil?
327
- identifiers = []
327
+ identifiers = []
328
328
  response['data'].each do |element|
329
329
  identifiers << { :name => element['display_name'], :identifier => element['id'] }
330
330
  end
331
331
  return identifiers
332
- end
332
+ end
333
333
  end
334
334
  unless response.nil?
335
335
  break if response["status"].eql?('ok')
@@ -343,6 +343,14 @@ module DTK
343
343
 
344
344
  no_tasks do
345
345
 
346
+ #
347
+ # Run shell command directly from main, use with CAUTION
348
+ #
349
+
350
+ def run_shell_command(line)
351
+ TOPLEVEL_BINDING.eval('self').execute_shell_command_internal(line)
352
+ end
353
+
346
354
  ##
347
355
  # Block that allows users to specify part of the code which is expected to run for longer duration
348
356
  #
@@ -379,7 +387,7 @@ module DTK
379
387
  name, usage = current_method_info
380
388
  results = usage.split(name.gsub(/_/,'-')).last || ""
381
389
  return results.split(' ')
382
- end
390
+ end
383
391
 
384
392
  #TODO: can make more efficient by having rest call that returns name from id, rather than using 'list path'
385
393
  #entity_id can be a name as well as an id
@@ -397,12 +405,12 @@ module DTK
397
405
  match = response['data'].find{|entity|entity_id == entity['id']}
398
406
  end
399
407
  unless match
400
- raise DTK::Client::DtkError, "Not able to resolve entity name, please provide #{entity_type} name."
408
+ raise DTK::Client::DtkError, "Not able to resolve entity name, please provide #{entity_type} name."
401
409
  end
402
410
  match['display_name']
403
411
  end
404
412
 
405
- def is_numeric_id?(possible_id)
413
+ def is_numeric_id?(possible_id)
406
414
  !possible_id.to_s.match(/^[0-9]+$/).nil?
407
415
  end
408
416
 
@@ -414,9 +422,9 @@ module DTK
414
422
  trap("INT", false)
415
423
  return line
416
424
  end
417
- end
425
+ end
418
426
  end
419
-
427
+
420
428
  def get_type_and_raise_error_if_invalid(about, default_about, type_options)
421
429
  about ||= default_about
422
430
  raise DTK::Client::DtkError, "Not supported type '#{about}' for list for current context level. Possible type options: #{type_options.join(', ')}" unless type_options.include?(about)
@@ -425,8 +433,22 @@ module DTK
425
433
 
426
434
  # check for delimiter '/', if present returns namespace and name for module/service
427
435
  # returns: namespace, name
428
- def get_namespace_and_name(input_remote_name)
429
- (input_remote_name||'').include?('/') ? input_remote_name.split('/') : [nil, input_remote_name]
436
+ def get_namespace_and_name(input_remote_name, delimiter)
437
+ (input_remote_name||'').include?(delimiter) ? input_remote_name.split(delimiter) : [nil, input_remote_name]
438
+ end
439
+
440
+ def get_namespace_and_name_for_component(component_full_name)
441
+ namespace, name = nil, ''
442
+
443
+ if (component_full_name||'').include?(':')
444
+ match = component_full_name.match(/(\w*\-?\w*):{1}(.*)/)
445
+ namespace, name = [$1,$2]
446
+
447
+ return [nil, component_full_name] if (name.include?(':') && !name.include?('::'))
448
+ component_full_name = name
449
+ end
450
+
451
+ [namespace, component_full_name]
430
452
  end
431
453
  end
432
454
 
@@ -448,7 +470,7 @@ module DTK
448
470
  end
449
471
 
450
472
  #
451
- # Returns list of invisible contexts with sufix provided (if any)
473
+ # Returns list of invisible contexts with sufix provided (if any)
452
474
  #
453
475
 
454
476
  def self.invisible_context_list(sufix = 'identifier')
@@ -459,7 +481,7 @@ module DTK
459
481
  def help(*args)
460
482
  puts # pretty print
461
483
  not_dtk_clazz = true
462
-
484
+
463
485
  if defined?(DTK::Client::Dtk)
464
486
  not_dtk_clazz = !self.class.eql?(DTK::Client::Dtk)
465
487
  end
data/lib/shell/context.rb CHANGED
@@ -748,13 +748,21 @@ module DTK
748
748
  def load_extended_context_commands(extended_context_commands, active_context_copy)
749
749
  candidates = []
750
750
  entity_name = active_context_copy.last_context
751
+ parent_entity = active_context_copy.context_list[1]
751
752
 
752
753
  if entity_name.is_identifier?
753
754
  endpoint = extended_context_commands[:endpoint]
754
755
  url = extended_context_commands[:url]
755
756
  opts = extended_context_commands[:opts]||{}
756
757
 
757
- id_label = "#{endpoint}_id".to_sym
758
+ if (parent_entity && parent_entity.is_identifier? && (parent_entity != entity_name))
759
+ parent_id_label = "#{endpoint}_id".to_sym
760
+ parent_id = parent_entity.identifier
761
+ opts[parent_id_label] = parent_id
762
+ id_label = "#{entity_name.entity}_id".to_sym
763
+ end
764
+
765
+ id_label ||= "#{endpoint}_id".to_sym
758
766
  id = entity_name.identifier
759
767
  opts[id_label] = id
760
768
 
@@ -968,7 +976,7 @@ module DTK
968
976
  private
969
977
 
970
978
  # list of commands that should be excluded from history
971
- EXCLUDE_COMMAND_LIST = ['create-provider']
979
+ EXCLUDE_COMMAND_LIST = ['create-provider','create-ec2-provider','create-physical-provider']
972
980
 
973
981
  def self.is_allowed_command?(full_command_entry)
974
982
  found = EXCLUDE_COMMAND_LIST.find { |cmd| full_command_entry.include?(cmd) }
data/lib/shell.rb CHANGED
@@ -17,7 +17,7 @@ require 'thor'
17
17
  $shell_mode = true
18
18
 
19
19
  ALIAS_COMMANDS = {
20
- 'ls' => 'list',
20
+ 'ls' => 'list',
21
21
  'cd' => 'cc',
22
22
  'rm' => 'delete'
23
23
  }
@@ -45,7 +45,7 @@ def run_shell_command()
45
45
  puts "\n"
46
46
  raise Interrupt
47
47
  }
48
-
48
+
49
49
  # runtime part
50
50
  begin
51
51
  while line = Readline.readline(prompt, true)
@@ -75,7 +75,7 @@ def init_shell_context()
75
75
  begin
76
76
  @context = DTK::Shell::Context.new
77
77
  @shell_header = DTK::Shell::HeaderShell.new
78
- # loads root context
78
+ # loads root context
79
79
  @context.load_context()
80
80
 
81
81
  @t1 = nil
@@ -121,10 +121,10 @@ def execute_shell_command(line, prompt)
121
121
  end
122
122
  end
123
123
 
124
-
124
+
125
125
  if ('cc' == cmd)
126
126
  # in case there is no params we just reload command
127
- args << "/" if args.empty?
127
+ args << "/" if args.empty?
128
128
  prompt = @context.change_context(args, cmd)
129
129
  elsif ('popc' == cmd)
130
130
  @context.dirs.shift()
@@ -149,9 +149,9 @@ def execute_shell_command(line, prompt)
149
149
 
150
150
  # get all next-context-candidates (e.g. for assembly get all assembly_names)
151
151
  context_candidates = @context.get_ac_candidates_for_context(@context.active_context.last_context(), @context.active_context())
152
-
152
+
153
153
  # this part of the code is used for calling of nested commands from base context (dtk:/>assembly/assembly_id converge)
154
- # base_command is used to check if first command from n-level is valid e.g.
154
+ # base_command is used to check if first command from n-level is valid e.g.
155
155
  # (dtk:/>assembly/assembly_id converge - chech if 'assembly' exists in context_candidates)
156
156
  # revert_context is used to return to context which command is called from after command is executed
157
157
  base_command = cmd.split('/').first
@@ -165,12 +165,12 @@ def execute_shell_command(line, prompt)
165
165
 
166
166
  if cmd.nil?
167
167
  prompt = @context.change_context(["-"]) if revert_context
168
- raise DTK::Client::DtkValidationError, "You have to provide command after context name. Usage: CONTEXT-TYPE/CONTEXT-NAME COMMAND [ARG1] .. [ARG2]."
168
+ raise DTK::Client::DtkValidationError, "You have to provide command after context name. Usage: CONTEXT-TYPE/CONTEXT-NAME COMMAND [ARG1] .. [ARG2]."
169
169
  end
170
170
 
171
171
  # send monkey patch class information about context
172
172
  Thor.set_context(@context)
173
-
173
+
174
174
  # we get command and hash params, will return Validation error if command is not valid
175
175
  entity_name, method_name, context_params, thor_options, invalid_options = @context.get_command_parameters(cmd,args)
176
176
 
@@ -178,7 +178,7 @@ def execute_shell_command(line, prompt)
178
178
  if context_candidates.include?(method_name)
179
179
  context_params.add_context_to_params(method_name, entity_name, method_name)
180
180
  method_name = context_params.method_arguments.shift if context_params.method_arguments.size > 0
181
- else
181
+ else
182
182
  unless @context.method_valid?(method_name)
183
183
  prompt = @context.change_context(["-"]) if revert_context
184
184
  raise DTK::Client::DtkValidationError, "Method '#{method_name}' is not valid in current context."
@@ -194,7 +194,7 @@ def execute_shell_command(line, prompt)
194
194
  # when 'delete' or 'delete-and-destroy' command is executed reload cached tasks with latest commands
195
195
  unless (args.nil? || args.empty?)
196
196
  @context.reload_cached_tasks(entity_name) if (method_name.include?('delete') || method_name.include?('import'))
197
- end
197
+ end
198
198
 
199
199
  # check execution status, prints status to sttout
200
200
  DTK::Shell::StatusMonitor.check_status()
@@ -210,10 +210,16 @@ def execute_shell_command(line, prompt)
210
210
  rescue DTK::Shell::Error => e
211
211
  DtkLogger.instance.error(e.message, true)
212
212
  end
213
-
213
+
214
214
  return prompt
215
215
  end
216
216
 
217
+ public
218
+
219
+ def execute_shell_command_internal(line)
220
+ execute_shell_command(line, DTK::Shell::Context::DTK_ROOT_PROMPT)
221
+ end
222
+
217
223
 
218
224
 
219
225
 
@@ -0,0 +1,41 @@
1
+ module DTK
2
+ module Client
3
+ module ModuleUtil
4
+
5
+ NAMESPACE_SEPERATOR = ':'
6
+
7
+ def self.resolve_name(module_name, module_namespace)
8
+ is_invalid = module_name.nil? || module_namespace.nil? || module_name.empty? || module_namespace.empty?
9
+ raise DtkError, "Failed to provide module name (#{module_name}) or namespace (#{module_namespace})" if is_invalid
10
+ "#{module_namespace}#{NAMESPACE_SEPERATOR}#{module_name}"
11
+ end
12
+
13
+ def self.join_name(module_name, module_namespace)
14
+ module_namespace ? resolve_name(module_name, module_namespace) : module_name
15
+ end
16
+
17
+ # returns [namespace,name]; namespace can be null if cant determine it
18
+ def self.full_module_name_parts?(name_or_full_module_name)
19
+ if name_or_full_module_name.nil?
20
+ return [nil,nil]
21
+ end
22
+ if name_or_full_module_name =~ Regexp.new("(^.+)#{NAMESPACE_SEPERATOR}(.+$)")
23
+ namespace,name = [$1,$2]
24
+ else
25
+ namespace,name = [nil,name_or_full_module_name]
26
+ end
27
+ [namespace,name]
28
+ end
29
+
30
+ def self.filter_module_name(name_or_full_module_name)
31
+ full_module_name_parts?(name_or_full_module_name).last
32
+ end
33
+
34
+ def self.check_format!(module_identifier)
35
+ return module_identifier if module_identifier.match(/^[0-9]+$/)
36
+ DtkLogger.instance.debug(caller)
37
+ raise DtkError, "Module name should be in following format NAMESPACE#{NAMESPACE_SEPERATOR}MODULE_NAME" unless module_identifier.match(Regexp.new("^.+#{NAMESPACE_SEPERATOR}.+$"))
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/util/os_util.rb CHANGED
@@ -100,7 +100,8 @@ module DTK
100
100
 
101
101
  def module_location(module_type,module_name,version=nil,opts={})
102
102
  # compact used because module_name can be nil
103
- module_location_parts(module_type,module_name,version,opts).compact.join('/')
103
+ location = module_location_parts(module_type,module_name,version,opts).compact.join('/')
104
+ location
104
105
  end
105
106
 
106
107
  # if module location is /a/b/d/mod it returns ['/a/b/d','mod']
@@ -116,7 +117,12 @@ module DTK
116
117
  ["#{base_all_types}/#{type}", module_name]
117
118
  end
118
119
  else
119
- [base_path, "#{module_name}#{version && "-#{version}"}"]
120
+ # we detect if we are using full name
121
+ if (module_name.match(/(.*)#{ModuleUtil::NAMESPACE_SEPERATOR}(.*)/))
122
+ [base_path, "#{$1}", "#{$2}#{version && "-#{version}"}"]
123
+ else
124
+ [base_path, "#{module_name}#{version && "-#{version}"}"]
125
+ end
120
126
  end
121
127
  end
122
128
 
@@ -127,7 +133,7 @@ module DTK
127
133
  end
128
134
 
129
135
  def module_clone_location(module_type)
130
- case module_type
136
+ case module_type.to_s
131
137
  when "component_module"
132
138
  return component_clone_location
133
139
  when "service_module"
@@ -135,7 +141,7 @@ module DTK
135
141
  when "test_module"
136
142
  test_clone_location
137
143
  else
138
- raise Client::DtkError, "Unexpected module_type (#{module_type})"
144
+ raise Client::DtkError, "Unexpected module_type (#{module_type}) when determining module location"
139
145
  end
140
146
  end
141
147
 
@@ -158,12 +164,12 @@ module DTK
158
164
  def clone_base_path(module_type)
159
165
 
160
166
  path =
161
- case module_type
167
+ case module_type.to_sym
162
168
  when :service_module then Config[:service_location]
163
169
  when :component_module then Config[:module_location]
164
170
  when :test_module then Config[:test_module_location]
165
171
  when :assembly_module then Config[:assembly_module_base_location]
166
- else raise Client::DtkError, "Unexpected module_type (#{module_type})"
172
+ else raise Client::DtkError, "Unexpected module_type (#{module_type}) when determining base path"
167
173
  end
168
174
 
169
175
 
@@ -189,7 +195,19 @@ module DTK
189
195
  #
190
196
  def local_component_module_list()
191
197
  component_module_dir = component_clone_location()
192
- Dir.entries(component_module_dir).select {|entry| File.directory? File.join(component_module_dir,entry) and !(entry =='.' || entry == '..') }
198
+
199
+ directories = Dir.entries(component_module_dir).map do |entry|
200
+ next if (entry =='.' || entry == '..' || entry.index('.') == 0)
201
+
202
+ Dir.entries("#{component_module_dir}/#{entry}").map do |m_entry|
203
+ next unless File.directory? File.join(component_module_dir,entry,m_entry)
204
+ next if (m_entry =='.' || m_entry == '..' || m_entry.index('.') == 0)
205
+
206
+ ModuleUtil.join_name(m_entry, entry)
207
+ end
208
+ end
209
+
210
+ directories.flatten.select { |d| !d.nil? }
193
211
  end
194
212
 
195
213
  # Public method will convert given string, to string with colorize output
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dtk-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.17
4
+ version: 0.5.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich PELAVIN
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-14 00:00:00.000000000 Z
11
+ date: 2014-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -210,6 +210,7 @@ files:
210
210
  - lib/commands.rb
211
211
  - lib/commands/common/thor/access_control.rb
212
212
  - lib/commands/common/thor/action_result_handler.rb
213
+ - lib/commands/common/thor/assembly_template.rb
213
214
  - lib/commands/common/thor/assembly_workspace.rb
214
215
  - lib/commands/common/thor/clone.rb
215
216
  - lib/commands/common/thor/common.rb
@@ -282,6 +283,7 @@ files:
282
283
  - lib/util/common_util.rb
283
284
  - lib/util/console.rb
284
285
  - lib/util/dtk_puppet.rb
286
+ - lib/util/module_util.rb
285
287
  - lib/util/os_util.rb
286
288
  - lib/util/permission_util.rb
287
289
  - lib/util/remote_dependency_util.rb