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
@@ -7,6 +7,9 @@ module DTK
7
7
  module Client
8
8
  #TODO: should make higher level class be above whether it is 'rest'
9
9
  class Response < Common::Response
10
+ require File.expand_path('response/error_handler',File.dirname(__FILE__))
11
+ include ErrorHandlerMixin
12
+
10
13
  # :render_view => symbol specifing type of data to be rendered e.g. :assembly
11
14
  # :skip_render => flag that specifies that render is not needed (default: false)
12
15
  # :print_error_table => we use it if we want to print 'error legend' for given tables (default: false)
@@ -230,6 +233,12 @@ module DTK
230
233
  end
231
234
  end
232
235
 
236
+ class NotOk < self
237
+ def initialize(data={})
238
+ super(nil,{"data"=> data, "status" => "notok"})
239
+ end
240
+ end
241
+
233
242
  class Error < self
234
243
  include Common::Response::ErrorMixin
235
244
  def initialize(hash={})
@@ -0,0 +1,61 @@
1
+ module DTK; module Client
2
+ class Response
3
+ module ErrorHandlerMixin
4
+ # opts can be
5
+ # :default_error_if_nil - Boolean
6
+ def error_info?(opts={})
7
+ ErrorHandler.error_info?(self,opts)
8
+ end
9
+ end
10
+
11
+ module ErrorHandler
12
+ SpecificErrorCodes = [:unauthorized,:session_timeout,:broken,:forbidden,:timeout,:connection_refused,:resource_not_found,:pg_error]
13
+ DefaultErrorCode = :error
14
+ DefaultErrorMsg = 'Internal DTK Client error, please try again'
15
+
16
+ Info = Struct.new(:msg,:code,:backtrace)
17
+ def self.error_info?(response,opts={})
18
+ unless errors = response["errors"]
19
+ return (opts[:default_error_if_nil] && error_info_default())
20
+ end
21
+
22
+ error_msg = ""
23
+ error_internal = nil
24
+ error_backtrace = nil
25
+ error_code = nil
26
+ error_on_server = nil
27
+
28
+ #TODO: below just 'captures' first error
29
+ errors.each do |err|
30
+ error_msg += err["message"] unless err["message"].nil?
31
+ error_msg += err["error"] unless err["error"].nil?
32
+ error_on_server = true unless err["on_client"]
33
+ error_code = err["code"]||(err["errors"] && err["errors"].first["code"])
34
+ error_internal ||= (err["internal"] or error_code == "not_found") #"not_found" code is at Ramaze level; so error_internal not set
35
+ error_backtrace ||= err["backtrace"]
36
+ end
37
+
38
+ # normalize it for display
39
+ error_msg = error_msg.empty? ? DefaultErrorMsg : "#{error_msg}"
40
+
41
+ unless error_code and SpecificErrorCodes.include?(error_code)
42
+ error_code =
43
+ if error_internal
44
+ error_on_server ? :server_error : :client_error
45
+ else
46
+ DefaultErrorCode
47
+ end
48
+ end
49
+
50
+ error_code = error_code.to_sym
51
+ Info.new(error_msg,error_code,error_backtrace)
52
+ end
53
+
54
+ def self.error_info_default()
55
+ Info.new(DefaultErrorMsg,DefaultErrorCode,nil)
56
+ end
57
+
58
+ end
59
+ end
60
+ end; end
61
+
@@ -1,3 +1,3 @@
1
1
  module DtkClient
2
- VERSION="0.7.4.1"
2
+ VERSION="0.7.5"
3
3
  end
data/lib/dtk_client.rb ADDED
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../client', __FILE__)
2
+ require File.expand_path('../configurator', __FILE__)
3
+ require File.expand_path('../parser/adapters/thor', __FILE__)
4
+ require File.expand_path('../shell/context', __FILE__)
5
+ require File.expand_path('../shell/domain/context_entity', __FILE__)
6
+ require File.expand_path('../shell/domain/active_context', __FILE__)
7
+ require File.expand_path('../shell/domain/context_params', __FILE__)
8
+ require File.expand_path('../shell/domain/override_tasks', __FILE__)
9
+ require File.expand_path('../shell/domain/shadow_entity', __FILE__)
10
+ require File.expand_path('../commands/thor/account', __FILE__)
11
+ require File.expand_path('../shell/parse_monkey_patch', __FILE__)
12
+ require File.expand_path('../shell/help_monkey_patch', __FILE__)
13
+ require File.expand_path('../execute/cli_pure/cli_rerouter', __FILE__)
14
+ require File.expand_path('../context_router', __FILE__)
data/lib/dtk_error.rb ADDED
@@ -0,0 +1,91 @@
1
+ module DTK
2
+ module Client
3
+ class DtkError < Error
4
+ def initialize(msg,opts={})
5
+ super(msg)
6
+ @backtrace = opts[:backtrace]
7
+ end
8
+ attr_reader :backtrace
9
+
10
+ def self.raise_error(response)
11
+ raise_if_error?(response,:default_error_if_nil => true)
12
+ end
13
+ def self.raise_if_error?(response,opts={})
14
+ # check for errors in response
15
+ unless error = response.error_info?(opts)
16
+ return
17
+ end
18
+
19
+ # if error_internal.first == true
20
+ case error.code
21
+ when :unauthorized
22
+ raise self, "[UNAUTHORIZED] Your session has been suspended, please log in again."
23
+ when :session_timeout
24
+ raise self, "[SESSION TIMEOUT] Your session has been suspended, please log in again."
25
+ when :broken
26
+ raise self, "[BROKEN] Unable to connect to the DTK server at host: #{Config[:server_host]}"
27
+ when :forbidden
28
+ raise DTK::Client::DtkLoginRequiredError, "[FORBIDDEN] Access not granted, please log in again."
29
+ when :timeout
30
+ raise self, "[TIMEOUT ERROR] Server is taking too long to respond."
31
+ when :connection_refused
32
+ raise self, "[CONNECTION REFUSED] Connection refused by server."
33
+ when :resource_not_found
34
+ raise self, "[RESOURCE NOT FOUND] #{error.msg}"
35
+ when :pg_error
36
+ raise self, "[PG_ERROR] #{error.msg}"
37
+ when :server_error
38
+ raise Server.new(error.msg,:backtrace => error.backtrace)
39
+ when :client_error
40
+ raise Client.new(error.msg,:backtrace => error.backtrace)
41
+ else
42
+ # if usage error occurred, display message to console and display that same message to log
43
+ raise Usage.new(error.msg)
44
+ end
45
+ end
46
+
47
+
48
+ class Usage < self
49
+ def initialize(error_msg,opts={})
50
+ msg_to_pass_to_super = "[ERROR] #{error_msg}"
51
+ super(msg_to_pass_to_super,opts)
52
+ end
53
+ end
54
+
55
+ class InternalError < self
56
+ def initialize(error_msg,opts={})
57
+ msg_to_pass_to_super = "[#{label(opts[:where])}] #{error_msg}"
58
+ super(msg_to_pass_to_super,opts)
59
+ end
60
+ def self.label(where=nil)
61
+ prefix = (where ? "#{where.to_s.upcase} " : '')
62
+ "#{prefix}#{InternalErrorLabel}"
63
+ end
64
+ InternalErrorLabel = 'INTERNAL ERROR'
65
+
66
+ private
67
+ def label(where=nil)
68
+ self.class.label(where)
69
+ end
70
+ end
71
+
72
+ class Client < InternalError
73
+ def initialize(error_msg,opts={})
74
+ super(error_msg,opts.merge(:where => :client))
75
+ end
76
+ def self.label(*args)
77
+ super(:client)
78
+ end
79
+ end
80
+ class Server < InternalError
81
+ def initialize(error_msg,opts={})
82
+ super(error_msg,opts.merge(:where => :server))
83
+ end
84
+ def self.label(*args)
85
+ super(:server)
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+ end
data/lib/error.rb CHANGED
@@ -8,6 +8,9 @@ module DTK
8
8
  class Error < NameError
9
9
  end
10
10
 
11
+ # DtkError is child of Error; so order matters
12
+ require File.expand_path('dtk_error', File.dirname(__FILE__))
13
+
11
14
  class DSLParsing < Error
12
15
  def initialize(base_json_error,file_path=nil)
13
16
  super(err_msg(base_json_error,file_path))
@@ -48,15 +51,6 @@ module DTK
48
51
  class DtkImplementationError < Error
49
52
  end
50
53
 
51
- # we use this to log application errors
52
- class DtkError < Error
53
- def initialize(msg,opts={})
54
- super(msg)
55
- @backtrace = opts[:backtrace]
56
- end
57
- attr_reader :backtrace
58
- end
59
-
60
54
  class DtkLoginRequiredError < Error
61
55
  end
62
56
 
@@ -0,0 +1,82 @@
1
+ module DTK
2
+ class CLIRerouter
3
+
4
+ ROUTER_DATA = {
5
+ :service_module => [
6
+ { :regex => /service-module (?<service_module_id>[\w:\-]+) (?<method_name>stage) (?<assembly_id>[\w:\-]+) (?<instance_name>[\w:\-\.\:]+)/, :entity => 'assembly' },
7
+ { :regex => /service-module (?<service_module_id>[\w:\-]+) (?<method_name>deploy) (?<assembly_id>[\w:\-]+) (?<instance_name>[\w:\-\.\:]+)/ }
8
+ ],
9
+ :service => [
10
+ { :regex => /service (?<service_id>[\w:\-]+) (?<method_name>set-attribute) (?<name>[\w:\-\.\:]+) (?<value>[\w:\-\.\:]+)/ },
11
+ { :regex => /service (?<service_id>[\w:\-]+) (?<method_name>converge)/ },
12
+ { :regex => /service (?<method_name>delete-and-destroy) (?<instance_name>[\w:\-]+)/ }
13
+ ]
14
+ }
15
+
16
+ def initialize(entity_name, args)
17
+ @cli_string = CLIRerouter.formulate_command_string(entity_name, args)
18
+ @entity_name = CLIRerouter.norm(entity_name)
19
+
20
+ ROUTER_DATA[@entity_name].each do |defintion|
21
+ if match = @cli_string.match(defintion[:regex])
22
+ @method_name = CLIRerouter.norm(match[:method_name])
23
+
24
+ # sometimes we need to override entity
25
+ @entity_name = defintion[:entity] if defintion[:entity]
26
+
27
+ # we need to filter out IDs
28
+ @entity_ids = match.names.collect { |k| k.to_s.end_with?('_id') ? { k => match[k] } : nil }.compact
29
+
30
+ if @entity_ids.empty?
31
+ # match 1 is method name, there is no id
32
+ @args = match[2, match.size]
33
+ else
34
+ # match 1, 2 are id and method name rest are args
35
+ @args = match[@entity_ids.size + 2, match.size]
36
+ end
37
+
38
+ break
39
+ end
40
+ end
41
+
42
+ @conn = ::DTK::Client::Session.get_connection()
43
+ exit if validate_connection(@conn)
44
+ end
45
+
46
+ def run
47
+ new_context_params = DTK::Shell::ContextParams.new
48
+
49
+ @entity_ids.each do |value_hash|
50
+ key = value_hash.keys.first
51
+ value = value_hash.values.first
52
+ entity_name_of_param = key.gsub('_id', '')
53
+ new_context_params.add_context_name_to_params(entity_name_of_param, entity_name_of_param, value)
54
+ end
55
+
56
+ new_context_params.method_arguments = @args
57
+ new_context_params.pure_cli_mode = true
58
+ DTK::Client::ContextRouter.routeTask(@entity_name, @method_name, new_context_params, @conn)
59
+ end
60
+
61
+ def self.is_candidate?(entity_name, args)
62
+ cli = formulate_command_string(entity_name, args)
63
+ if definitions = ROUTER_DATA[norm(entity_name)]
64
+ is_match = definitions.find { |d| cli.match(d[:regex]) }
65
+
66
+ return true if is_match
67
+ end
68
+
69
+ return false
70
+ end
71
+
72
+ private
73
+
74
+ def self.norm(string_value)
75
+ return string_value ? string_value.gsub('-','_').to_sym : nil
76
+ end
77
+
78
+ def self.formulate_command_string(entity_name, args)
79
+ "#{entity_name} #{args.join(' ')}".strip()
80
+ end
81
+ end
82
+ end
@@ -329,6 +329,9 @@ module DTK
329
329
  unless response['data'].nil?
330
330
  identifiers = []
331
331
  response['data'].each do |element|
332
+ # special flag to filter out data not needed here
333
+ next if element['dtk_context_hidden']
334
+
332
335
  identifiers << { :name => element['display_name'], :identifier => element['id'], :shadow_entity => element['dtk_client_type'] }
333
336
  end
334
337
  return identifiers
data/lib/shell.rb CHANGED
@@ -60,7 +60,8 @@ def run_shell_command()
60
60
  #system('stty', stty_save) # Restore
61
61
  retry
62
62
  rescue Exception => e
63
- DtkLogger.instance.error_pp("[CLI INTERNAL ERROR] #{e.message}", e.backtrace)
63
+ client_internal_error = DTK::Client::DtkError::Client.label()
64
+ DtkLogger.instance.error_pp("[#{client_internal_error}] #{e.message}", e.backtrace)
64
65
  ensure
65
66
  puts "\n" unless e.is_a? DTK::Shell::ExitSignal
66
67
  # logout
@@ -3,11 +3,13 @@ module DTK::Shell
3
3
 
4
4
  attr_accessor :current_context
5
5
  attr_accessor :method_arguments
6
+ attr_accessor :pure_cli_mode
6
7
 
7
8
  def initialize(override_method_arguments = [])
8
9
  @current_context = ActiveContext.new
9
10
  @method_arguments = override_method_arguments
10
11
  @thor_options = Hash.new
12
+ @pure_cli_mode = false
11
13
 
12
14
  @method_arguments
13
15
  end
data/lib/util/console.rb CHANGED
@@ -39,7 +39,7 @@ module DTK::Client
39
39
  def confirmation_prompt_simple(message, add_options=true)
40
40
  # used to disable skip with ctrl+c
41
41
  trap("INT", "SIG_IGN")
42
- message += " (Y/n)" if add_options
42
+ message += " (y/n)" if add_options
43
43
 
44
44
  while line = Readline.readline("#{message}: ", true)
45
45
  if (line.eql?("yes") || line.eql?("y") || line.empty?)
data/lib/util/os_util.rb CHANGED
@@ -295,6 +295,7 @@ module DTK
295
295
  load File.expand_path('../../lib/domain/git_adapter.rb', File.dirname(__FILE__))
296
296
  load File.expand_path('../../lib/command_helpers/git_repo.rb', File.dirname(__FILE__))
297
297
  load File.expand_path('../../lib/command_helpers/service_importer.rb', File.dirname(__FILE__))
298
+ load File.expand_path('../../lib/view_processor/table_print.rb', File.dirname(__FILE__))
298
299
  paths = []
299
300
  paths << File.expand_path('../../lib/commands/thor/*.rb', File.dirname(__FILE__))
300
301
  paths << File.expand_path('../../lib/commands/common/thor/*.rb', File.dirname(__FILE__))
@@ -4,17 +4,19 @@
4
4
  module DTK
5
5
  module Client
6
6
  module RemoteDependencyUtil
7
-
8
7
  MODULE_REF_FILE = 'module_refs.yaml'
9
8
 
10
9
  class << self
11
-
12
- def print_dependency_warnings(response, success_msg=nil)
10
+ def print_dependency_warnings(response, success_msg = nil, opts = {})
13
11
  are_there_warnings = false
14
12
  return are_there_warnings if response.nil? || response.data.nil?
15
13
 
16
14
  warnings = response.data['dependency_warnings']
17
15
  if warnings && !warnings.empty?
16
+ if opts[:ignore_permission_warnings]
17
+ warnings.delete_if { |warning| warning['error_type'].eql?('no_permission') }
18
+ return if warnings.empty?
19
+ end
18
20
  print_out "Following warnings have been detected for current module by Repo Manager:\n"
19
21
  warnings.each { |w| print_out(" - #{w['message']}") }
20
22
  puts
@@ -24,6 +26,21 @@ module DTK
24
26
  are_there_warnings
25
27
  end
26
28
 
29
+ def check_permission_warnings(response)
30
+ errors = ''
31
+ dependency_warnings = response.data['dependency_warnings']
32
+
33
+ if dependency_warnings && !dependency_warnings.empty?
34
+ no_permissions = dependency_warnings.select { |warning| warning['error_type'].eql?('no_permission') }
35
+
36
+ errors << "\n\nYou do not have (R) permissions for modules:\n\n"
37
+ no_permissions.each { |np| errors << " - #{np['module_namespace']}:#{np['module_name']} (owner: #{np['module_owner']})\n" }
38
+ errors << "\nPlease contact owner(s) to change permissions for those modules."
39
+ end
40
+
41
+ raise DtkError, errors unless errors.empty?
42
+ end
43
+
27
44
  def module_ref_content(location)
28
45
  abs_location = File.join(location, MODULE_REF_FILE)
29
46
  File.exists?(abs_location) ? File.read(abs_location) : nil
@@ -21,6 +21,11 @@ class DtkOpenStruct < OpenStruct
21
21
  end
22
22
  end
23
23
 
24
+ # [Haris]
25
+ # Elements with action column (taks status) have been removed since they are no longer in use. In case of bug that is relying
26
+ # on existance of element and logic, please contact me to resolve it.
27
+ #
28
+
24
29
  module DTK
25
30
  module Client
26
31
  class ViewProcTablePrint < ViewProcessor
@@ -41,6 +46,7 @@ module DTK
41
46
 
42
47
  def initialize(data, data_type, forced_metadata, print_error_table)
43
48
  # if there is no custom metadata, then we use metadata predefined in meta-response.json file
49
+
44
50
  if forced_metadata.nil?
45
51
  # get all table definitions from json file
46
52
  @table_defintions = get_metadata()
@@ -84,7 +90,7 @@ module DTK
84
90
  evaluated_element = DtkOpenStruct.new
85
91
  error_element = DtkOpenStruct.new
86
92
 
87
- # based on mappign we set key = eval(value)
93
+ # based on mapping we set key = eval(value)
88
94
  table_defintion.each do |k,v|
89
95
  begin
90
96
  # due to problems with space we have special way of handling error columns
@@ -124,29 +130,6 @@ module DTK
124
130
  # add it with other
125
131
  @error_data << error_element
126
132
  end
127
- elsif k.include?('action')
128
- error_message = value_of(structured_element, v)
129
-
130
- # here we see if there was an error if not we will skip this
131
- # if so we add it to @error_data
132
-
133
- if error_message.empty?
134
- # no error message just add it as regular element
135
- evaluated_element.send("#{k}=",value_of(structured_element, v))
136
- else
137
- error_index = "[ #{value_of(structured_element,'logs.label')} ]" || ""
138
- error_type = value_of(structured_element,'logs.dtk_type') || ""
139
-
140
- # original table takes that index
141
- evaluated_element.send("#{k}=", error_index)
142
-
143
- # we set new error element
144
- error_element.id = error_index
145
- error_element.message = error_message
146
-
147
- # add it with other
148
- @action_data << error_element
149
- end
150
133
  else
151
134
  evaluated_element.send("#{k}=", value_of(structured_element, v))
152
135
  # eval "evaluated_element.#{k}=structured_element.#{v}"
@@ -161,7 +144,6 @@ module DTK
161
144
  end
162
145
  end
163
146
 
164
- @order_definition.delete('action')
165
147
  @order_definition.delete('errors')
166
148
 
167
149
  @evaluated_data << evaluated_element