dtk-client 0.7.4.1 → 0.7.5

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/bin/dtk +10 -3
  3. data/bin/dtk-shell +1 -1
  4. data/lib/command_helpers/git_repo.rb +26 -20
  5. data/lib/command_helpers/jenkins_client.rb +4 -3
  6. data/lib/command_helpers/service_importer.rb +37 -25
  7. data/lib/commands.rb +2 -2
  8. data/lib/commands/common/thor/assembly_workspace.rb +185 -173
  9. data/lib/commands/common/thor/base_command_helper.rb +42 -0
  10. data/lib/commands/common/thor/clone.rb +1 -1
  11. data/lib/commands/common/thor/module.rb +37 -58
  12. data/lib/commands/common/thor/module/import.rb +1 -1
  13. data/lib/commands/common/thor/pull_from_remote.rb +7 -12
  14. data/lib/commands/common/thor/purge_clone.rb +1 -1
  15. data/lib/commands/common/thor/push_clone_changes.rb +3 -1
  16. data/lib/commands/common/thor/task_status.rb +52 -75
  17. data/lib/commands/common/thor/task_status/refresh_mode.rb +56 -0
  18. data/lib/commands/common/thor/task_status/snapshot_mode.rb +11 -0
  19. data/lib/commands/common/thor/task_status/stream_mode.rb +31 -0
  20. data/lib/commands/common/thor/task_status/stream_mode/element.rb +90 -0
  21. data/lib/commands/common/thor/task_status/stream_mode/element/no_results.rb +10 -0
  22. data/lib/commands/common/thor/task_status/stream_mode/element/render.rb +88 -0
  23. data/lib/commands/common/thor/task_status/stream_mode/element/stage.rb +13 -0
  24. data/lib/commands/common/thor/task_status/stream_mode/element/task_end.rb +10 -0
  25. data/lib/commands/common/thor/task_status/stream_mode/element/task_start.rb +10 -0
  26. data/lib/commands/thor/account.rb +10 -8
  27. data/lib/commands/thor/assembly.rb +9 -2
  28. data/lib/commands/thor/component_module.rb +0 -52
  29. data/lib/commands/thor/library.rb +1 -0
  30. data/lib/commands/thor/node.rb +1 -36
  31. data/lib/commands/thor/node_template.rb +4 -47
  32. data/lib/commands/thor/service.rb +57 -46
  33. data/lib/commands/thor/service_module.rb +2 -49
  34. data/lib/commands/thor/target.rb +7 -7
  35. data/lib/commands/thor/workspace.rb +44 -27
  36. data/lib/context_router.rb +4 -0
  37. data/lib/core.rb +71 -99
  38. data/lib/domain/response.rb +9 -0
  39. data/lib/domain/response/error_handler.rb +61 -0
  40. data/lib/dtk-client/version.rb +1 -1
  41. data/lib/dtk_client.rb +14 -0
  42. data/lib/dtk_error.rb +91 -0
  43. data/lib/error.rb +3 -9
  44. data/lib/execute/cli_pure/cli_rerouter.rb +82 -0
  45. data/lib/parser/adapters/thor.rb +3 -0
  46. data/lib/shell.rb +2 -1
  47. data/lib/shell/domain/context_params.rb +2 -0
  48. data/lib/util/console.rb +1 -1
  49. data/lib/util/os_util.rb +1 -0
  50. data/lib/util/remote_dependency_util.rb +20 -3
  51. data/lib/view_processor/table_print.rb +7 -25
  52. metadata +17 -5
  53. data/lib/commands/common/thor/test_action_agent.rb +0 -39
  54. data/lib/commands/thor/repo.rb +0 -35
@@ -0,0 +1,56 @@
1
+ module DTK::Client
2
+ class TaskStatus
3
+ class RefreshMode < self
4
+ def task_status(opts={})
5
+ begin
6
+ response = nil
7
+ loop do
8
+ response = post_call(opts)
9
+ return response unless response.ok?
10
+
11
+ # stop pulling when top level task succeds, fails or timeout
12
+ if response and response.data and response.data.first
13
+ #TODO: may fix in server, but now top can have non executing state but a concurrent branch can execute; so
14
+ #chanding bloew for time being
15
+ #break unless response.data.first["status"].eql? "executing"
16
+ # TODO: There is bug where we do not see executing status on start so we have to wait until at
17
+ # least one 'successed' has been found
18
+
19
+ top_task_failed = response.data.first['status'].eql?('failed')
20
+ is_pending = (response.data.select {|r|r["status"].nil? }).size > 0
21
+ is_executing = (response.data.select {|r|r["status"].eql? "executing"}).size > 0
22
+ is_failed = (response.data.select {|r|r["status"].eql? "failed"}).size > 0
23
+ is_cancelled = response.data.first["status"].eql?("cancelled")
24
+
25
+ # commented out because of DTK-1804
26
+ # when some of the converge tasks fail, stop task-status --wait and set task status to '' for remaining tasks which are not executed
27
+ # if is_failed
28
+ # response.data.each {|r| (r["status"] = "") if r["status"].eql?("executing")}
29
+ # is_cancelled = true
30
+ # end
31
+ is_cancelled = true if top_task_failed
32
+
33
+ unless (is_executing || is_pending) && !is_cancelled
34
+ system('clear')
35
+ response.print_error_table = true
36
+ response.render_table(:task_status)
37
+ return response
38
+ end
39
+ end
40
+
41
+ response.render_table(:task_status)
42
+ system('clear')
43
+ response.render_data(true)
44
+
45
+ Console.wait_animation("Watching '#{@object_type}' task status [ #{DEBUG_SLEEP_TIME} seconds refresh ] ", DEBUG_SLEEP_TIME)
46
+ end
47
+ rescue Interrupt => e
48
+ puts ""
49
+ # this tells rest of the flow to skip rendering of this response
50
+ response.skip_render = true unless response.nil?
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,11 @@
1
+ module DTK::Client
2
+ class TaskStatus
3
+ class SnapshotMode < self
4
+ def task_status(opts={})
5
+ response = post_call(opts)
6
+ response.print_error_table = true
7
+ response.render_table(:task_status)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ require 'hirb'
2
+ module DTK::Client
3
+ class TaskStatus
4
+ class StreamMode < self
5
+ require File.expand_path('stream_mode/element',File.dirname(__FILE__))
6
+
7
+ def get_and_render()
8
+ Element.get_and_render_task_start(self)
9
+ Element.get_and_render_stages(self,:wait => WaitWhenNoResults)
10
+ Response::Ok.new()
11
+ end
12
+
13
+ WaitWhenNoResults = 5 #in seconds
14
+ # making this public for this class and its children
15
+ def post_call(*args)
16
+ super
17
+ end
18
+
19
+ private
20
+
21
+ # This uses a cursor based interface to the server
22
+ # start_index: START_INDEX
23
+ # end_index: END_INDEX
24
+ # convention is start_position = 0 and end_position = 0 means top level task with start time
25
+ def post_body(opts={})
26
+ ret = super(opts)
27
+ ret.merge(:start_index => opts[:start_index], :end_index => opts[:end_index])
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,90 @@
1
+ module DTK::Client; class TaskStatus::StreamMode
2
+ class Element
3
+ require File.expand_path('element/task_start',File.dirname(__FILE__))
4
+ require File.expand_path('element/task_end',File.dirname(__FILE__))
5
+ require File.expand_path('element/stage',File.dirname(__FILE__))
6
+ require File.expand_path('element/no_results',File.dirname(__FILE__))
7
+ require File.expand_path('element/render',File.dirname(__FILE__))
8
+ include RenderMixin
9
+
10
+ def initialize(response_element)
11
+ @response_element = response_element
12
+ end
13
+
14
+ def self.get_and_render_task_start(task_status_handle)
15
+ render_elements(TaskStart.get(task_status_handle))
16
+ end
17
+
18
+ # opts has
19
+ # :wait - amount to wait if get no results (required)
20
+ def self.get_and_render_stages(task_status_handle,opts={})
21
+ unless wait = opts[:wait]
22
+ raise DtkError::Client, "opts[:wait] must be set"
23
+ end
24
+
25
+ stage = 1
26
+ task_end = false
27
+ until task_end do
28
+ elements = Stage.get(task_status_handle,stage)
29
+ if no_results_yet?(elements)
30
+ sleep wait
31
+ next
32
+ end
33
+
34
+ render_elements(elements)
35
+
36
+ if task_end?(elements)
37
+ task_end = true
38
+ else
39
+ stage += 1
40
+ end
41
+ end
42
+ end
43
+
44
+ def render()
45
+ #TODO: stub
46
+ #TODO: make this nil and overwride all elements types to render
47
+ pp [:element,self.class,self]
48
+ end
49
+
50
+ private
51
+ # opts will have
52
+ # :start_index
53
+ # :end_index
54
+ def self.get_task_status_elements(task_status_handle,element_type,opts={})
55
+ response = task_status_handle.post_call(opts.merge(:form => :stream_form))
56
+ create_elements(response)
57
+ end
58
+
59
+ def self.create_elements(response)
60
+ response_elements = response.data
61
+ unless response_elements.kind_of?(Array)
62
+ raise DtkError::Client.new("Unexpected that response.data no at array")
63
+ end
64
+ response_elements.map{|el|create(el)}
65
+ end
66
+ def self.create(response_element)
67
+ type = response_element['type']
68
+ case type && type.to_sym
69
+ when :task_start then TaskStart.new(response_element)
70
+ when :task_end then TaskEnd.new(response_element)
71
+ when :stage then Stage.new(response_element)
72
+ when :no_results then NoResults.new(response_element)
73
+ else raise DtkError::Client.new("Unexpected element type '#{type}'")
74
+ end
75
+ end
76
+
77
+ def self.task_end?(elements)
78
+ elements.empty? or elements.last.kind_of?(TaskEnd)
79
+ end
80
+
81
+ def self.no_results_yet?(elements)
82
+ elements.find{|el|el.kind_of?(NoResults)}
83
+ end
84
+
85
+ def self.render_elements(elements)
86
+ elements.each{|el|el.render()}
87
+ end
88
+
89
+ end
90
+ end; end
@@ -0,0 +1,10 @@
1
+ module DTK::Client; class TaskStatus::StreamMode
2
+ class Element
3
+ class NoResults < self
4
+ def task_end?()
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end; end
10
+
@@ -0,0 +1,88 @@
1
+ module DTK::Client; class TaskStatus::StreamMode
2
+ class Element
3
+ module RenderMixin
4
+ end
5
+ end
6
+ end; end
7
+
8
+ =begin
9
+ def task_status_old()
10
+ current_index = 1
11
+ last_printed_index = 0
12
+ success_indices = []
13
+ loop do
14
+ response = post_call(:form => :stream_form)
15
+ return response unless response.ok?
16
+
17
+ current_tasks = response.data.select { |el| el['index'] == current_index }
18
+ main_task = current_tasks.find { |el| el['sub_index'].nil? }
19
+
20
+ # this means this is last tasks
21
+ unless main_task
22
+ print_succeeded_tasks(response.data, success_indices)
23
+ return Response::Ok.new()
24
+ end
25
+
26
+ case main_task['status']
27
+ when 'executing'
28
+ if (last_printed_index != current_index)
29
+ OsUtil.clear_screen
30
+ print_succeeded_tasks(response.data, success_indices)
31
+ print_tasks(current_tasks)
32
+ last_printed_index = current_index
33
+ end
34
+ when 'succeeded'
35
+ success_indices << current_index
36
+ current_index += 1
37
+ when nil
38
+ # ignore
39
+ else
40
+ errors = current_tasks.collect { |ct| ct['errors'] }.compact
41
+ error_msg = errors.collect { |err| err['message'] }.uniq.join(', ')
42
+ raise DtkError, "We've run into an error on task '#{main_task['type']}' status '#{main_task['status']}', error: #{error_msg}"
43
+ end
44
+
45
+ sleep(5)
46
+ end
47
+ end
48
+
49
+ private
50
+ def print_tasks(tasks)
51
+ hirb_options = {
52
+ :headers => nil,
53
+ :filters => [Proc.new { |a| append_to(25, a) },
54
+ Proc.new { |a| append_to(15, a)},
55
+ Proc.new { |a| append_to(15, a)},
56
+ Proc.new { |a| append_to(8, a)}],
57
+ :unicode => true,
58
+ :description => false
59
+ }
60
+
61
+ tasks.each do |task|
62
+ node_name = task['node'] ? task['node']['name'] : ''
63
+
64
+ puts Hirb::Helpers::AutoTable.render([[task['type'], task['status'], node_name, task['duration'], parse_date(task['started_at']), parse_date(task['ended_at'])]], hirb_options)
65
+ end
66
+ end
67
+
68
+ def print_succeeded_tasks(tasks, success_indices)
69
+ succeeded_tasks = tasks.select { |task| success_indices.include?(task['index']) }
70
+ print_tasks(succeeded_tasks)
71
+ end
72
+
73
+ def parse_date(string_date)
74
+ string_date.nil? ? (' ' * 17) : DateTime.parse(string_date).strftime('%H:%M:%S %d/%m/%y')
75
+ end
76
+
77
+ def append_to(number_of_chars, value)
78
+ value ||= ''
79
+ value.strip!
80
+ appending_str = ' ' * (number_of_chars - value.size)
81
+ value.insert(0, appending_str)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ =end
88
+
@@ -0,0 +1,13 @@
1
+ module DTK::Client; class TaskStatus::StreamMode
2
+ class Element
3
+ class Stage < self
4
+ def self.get(task_status_handle,stage_num)
5
+ get_stages(task_status_handle,stage_num,stage_num)
6
+ end
7
+
8
+ def self.get_stages(task_status_handle,start_stage_num,end_stage_num)
9
+ get_task_status_elements(task_status_handle,:stage,:start_index => start_stage_num, :end_index => end_stage_num)
10
+ end
11
+ end
12
+ end
13
+ end; end
@@ -0,0 +1,10 @@
1
+ module DTK::Client; class TaskStatus::StreamMode
2
+ class Element
3
+ class TaskEnd < self
4
+ def task_end?()
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end; end
10
+
@@ -0,0 +1,10 @@
1
+ module DTK::Client; class TaskStatus::StreamMode
2
+ class Element
3
+ class TaskStart < self
4
+ def self.get(task_status_handle)
5
+ get_task_status_elements(task_status_handle,:task_start,:start_index => 0, :end_index => 0)
6
+ end
7
+ end
8
+ end
9
+ end; end
10
+
@@ -33,7 +33,7 @@ module DTK::Client
33
33
  [response, key_exists_already]
34
34
  end
35
35
 
36
- def self.add_key(path_to_key, name='dtk-client')
36
+ def self.add_key(path_to_key, first_registration=false, name='dtk-client')
37
37
  match, matched_username = nil, nil
38
38
 
39
39
  unless File.file?(path_to_key)
@@ -45,6 +45,7 @@ module DTK::Client
45
45
 
46
46
  post_body = { :rsa_pub_key => rsa_pub_key.chomp }
47
47
  post_body.merge!(:username => name.chomp) if name
48
+ post_body.merge!(:first_registration => first_registration)
48
49
 
49
50
  proper_response = nil
50
51
  response, key_exists_already = Account.internal_add_user_access("account/add_user_direct_access", post_body, 'service module')
@@ -58,7 +59,8 @@ module DTK::Client
58
59
  repo_manager_fingerprint,repo_manager_dns = response.data_ret_and_remove!(:repo_manager_fingerprint,:repo_manager_dns)
59
60
 
60
61
  SSHUtil.update_ssh_known_hosts(repo_manager_dns,repo_manager_fingerprint)
61
- name ||= response.data["new_username"]
62
+ name = response.data["new_username"]
63
+
62
64
  OsUtil.print("SSH key '#{name}' added successfully!", :yellow)
63
65
 
64
66
  end
@@ -117,7 +119,7 @@ module DTK::Client
117
119
  name, path_to_key = context_params.retrieve_arguments([:option_1!, :option_2],method_argument_names)
118
120
  path_to_key ||= SSHUtil.default_rsa_pub_key_path()
119
121
 
120
- response, matched, matched_username = Account.add_key(path_to_key, name)
122
+ response, matched, matched_username = Account.add_key(path_to_key, false, name)
121
123
 
122
124
  if matched
123
125
  DTK::Client::OsUtil.print("Provided SSH pub key has already been added.", :yellow)
@@ -127,8 +129,8 @@ module DTK::Client
127
129
  DTK::Client::Configurator.add_current_user_to_direct_access() if response.ok?
128
130
  end
129
131
 
130
- if response.ok? && !response.data(:registered_with_repoman)
131
- OsUtil.print("Warning: We were not able to register your key with remote catalog! Contact DTK team for more infromation.", :yellow)
132
+ if response.ok? && response.data(:repoman_registration_error)
133
+ OsUtil.print("Warning: We were not able to register your key with remote catalog! #{response.data(:repoman_registration_error)}", :yellow)
132
134
  end
133
135
 
134
136
  response.ok? ? nil : response
@@ -147,8 +149,8 @@ module DTK::Client
147
149
  response = post rest_url("account/remove_user_direct_access"), { :username => name.chomp }
148
150
  return response unless response.ok?
149
151
 
150
- if response.ok? && !response.data(:unregistered_with_repoman)
151
- OsUtil.print("Warning: We were not able to unregister your key with remote catalog!", :yellow)
152
+ if response.ok? && response.data(:repoman_registration_error)
153
+ OsUtil.print("Warning: We were not able to unregister your key with remote catalog! #{response.data(:repoman_registration_error)}", :yellow)
152
154
  end
153
155
 
154
156
  OsUtil.print("SSH key '#{name}' removed successfully!", :yellow)
@@ -171,7 +173,7 @@ module DTK::Client
171
173
  def set_catalog_credentials(context_params)
172
174
  creds = DTK::Client::Configurator.enter_catalog_credentials()
173
175
 
174
- response = post rest_url("account/set_catalog_credentials"), { :username => creds[:username], :password => creds[:password] }
176
+ response = post rest_url("account/set_catalog_credentials"), { :username => creds[:username], :password => creds[:password], :validate => true }
175
177
  return response unless response.ok?
176
178
 
177
179
  OsUtil.print("Your catalog credentials have been set!", :yellow)
@@ -194,11 +194,14 @@ module DTK::Client
194
194
  :type => :string
195
195
  method_option :settings, :type => :string, :aliases => '-s'
196
196
  def stage(context_params)
197
- assembly_template_id, name = context_params.retrieve_arguments([:assembly_id!, :option_1],method_argument_names)
197
+ assembly_template_id, service_module_id, name = context_params.retrieve_arguments([:assembly_id!, :service_module_id, :option_1],method_argument_names)
198
198
  post_body = {
199
199
  :assembly_id => assembly_template_id
200
200
  }
201
201
 
202
+ # special case when we need service module id
203
+ post_body[:service_module_id] = service_module_id if context_params.pure_cli_mode
204
+
202
205
  # using this to make sure cache will be invalidated after new assembly is created from other commands e.g.
203
206
  # 'assembly-create', 'install' etc.
204
207
  @@invalidate_map << :assembly
@@ -251,10 +254,14 @@ module DTK::Client
251
254
  method_option :settings, :type => :string, :aliases => '-s'
252
255
  def deploy(context_params)
253
256
  context_params.forward_options(options)
254
- assembly_template_id, name = context_params.retrieve_arguments([:assembly_id!, :option_1],method_argument_names)
257
+ assembly_template_id, service_module_id, name = context_params.retrieve_arguments([:assembly_id!, :service_module_id, :option_1],method_argument_names)
255
258
  post_body = {
256
259
  :assembly_id => assembly_template_id
257
260
  }
261
+
262
+ # special case when we need service module id
263
+ post_body[:service_module_id] = service_module_id if context_params.pure_cli_mode
264
+
258
265
  if commit_msg = options["commit_msg"]
259
266
  post_body.merge!(:commit_msg => commit_msg)
260
267
  end
@@ -326,58 +326,6 @@ module DTK::Client
326
326
  list_collaborators_module_aux(context_params)
327
327
  end
328
328
 
329
-
330
- #### end: commands to interact with remote repo ###
331
-
332
- #### commands to manage workspace and versioning ###
333
- =begin
334
- desc "COMPONENT-MODULE-NAME/ID create-version VERSION", "Snapshot current state of component module as a new version"
335
- def create_version(context_params)
336
- component_module_id,version = context_params.retrieve_arguments([:component_module_id!,:option_1!],method_argument_names)
337
-
338
- post_body = {
339
- :component_module_id => component_module_id,
340
- :rsa_pub_key => SSHUtil.rsa_pub_key_content()
341
- }
342
- response = post rest_url("component_module/versions"), post_body
343
- return response unless response.ok?
344
- versions = (response.data.first && response.data.first['versions'])||Array.new
345
- if versions.include?(version)
346
- return Response::Error::Usage.new("Version #{version} exists already")
347
- end
348
-
349
- component_module_name = get_module_name(component_module_id)
350
- module_location = OsUtil.module_location(:component_module,component_module_name,version)
351
- if File.directory?(module_location)
352
- return Response::Error::Usage.new("Target component module directory for version #{version} (#{module_location}) exists already; it must be deleted and this comamnd retried")
353
- end
354
-
355
- post_body = {
356
- :component_module_id => component_module_id,
357
- :version => version
358
- }
359
- response = post rest_url("component_module/create_new_version"), post_body
360
- return response unless response.ok?
361
-
362
- internal_trigger = omit_output = true
363
- clone_aux(:component_module,component_module_id,version,internal_trigger,omit_output)
364
- end
365
- =end
366
- =begin
367
- desc "COMPONENT-MODULE-NAME/ID list-versions","List all versions associated with this component module."
368
- def list_versions(context_params)
369
- component_module_id = context_params.retrieve_arguments([:component_module_id!],method_argument_names)
370
- post_body = {
371
- :component_module_id => component_module_id,
372
- :detail_to_include => ["remotes"],
373
- :rsa_pub_key => SSHUtil.rsa_pub_key_content()
374
- }
375
- response = post rest_url("component_module/versions"), post_body
376
-
377
- response.render_table(:module_version)
378
- end
379
- =end
380
-
381
329
  ##
382
330
  #
383
331
  # internal_trigger: this flag means that other method (internal) has trigger this.