dtk-client 0.5.9 → 0.5.10

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGM2YzcyZjU0NTk3ZmY1MTUyYzJlZjQ3YmFkYzhjOGE5N2M4OTUxZQ==
4
+ ZDEyNmM1MGE3NzA2MzQ5OGMyMzhhNDVjZDUxY2JkMmE0MTYxNDFkYQ==
5
5
  data.tar.gz: !binary |-
6
- YWJlMTcxYzE0OGQwYWJlZjZjM2E4NTIxNGY5YTZmZjY1ZTk2ZjM0NQ==
6
+ MWRiODEwOTRkYjNkZDRhNzI4ZjNmNjVjZmQ3ODQwMmI1Y2VjMTQwNQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZWY1YmJlODNlOGEzYTU5ZGFiYzlhOTdmZDNlYTM0Y2QzNjllOTQyZDZkNjM0
10
- NGQ5ZDUxZDg2YjA0MmQ2NTUwNDNkNDkwNzFjZDc3NGYyZDgxMGRhZmQyY2Rh
11
- MTc4Yzc2OTJjZjRkYmM3ZjEyYzRlMjBiNGQzMGM3OTM3Njk5MGQ=
9
+ MjE1MzUwZTNlZTMzMWY3OTRkMWJhNGJmNDQyZjU2YTM2YjkwYWFhZjczZjRh
10
+ ODY2NTVjOTI5M2Y2YzVkYjFhMzlhMmYzMTcwZDZiZmNjZDNmM2VhZWIzZGY3
11
+ MzMyYzBlZDM3ZDQxNjVlOGQ4MjYzNmY3ZWEwMmE1OTIxYjkzNDY=
12
12
  data.tar.gz: !binary |-
13
- YjkxNDdhOGEwNzI0MWZhNGI4OWEzNjQ4YjM3ZWEzYzA2MWM3NGExM2Y1MGMw
14
- ZWE2ZDI1NWFjYjUzODI5MDBkMDZjMTA3Y2I2ZmYyMTNiOThhOTExZWMzY2Iz
15
- OTEwMWJkZDc0NDljYjY1ZDM1ZWU1MDk1ZjIwMjBkM2VmYjc0YTQ=
13
+ MzQwYzQ0YjhkOTRlNzkyZDJjZDQ1NzY1ZjMxYjc3ZGE5NmEyYTlmMjVmNTlj
14
+ NGU3NzMzMWE1ZGE5MTc0ZGMxNDY2MWQ4MTU0MjhkNjZlY2MzOWM3MjQyOWQx
15
+ MDYyNjMzNmI4MDlhZTkwYzIwNWQ0MWNmN2VmMzUwMWYzYzYwMDY=
data/bin/dtk CHANGED
@@ -24,7 +24,7 @@ $: << "/usr/lib/ruby/1.8/" #TODO: put in to get around path problem in rvm 1.9.2
24
24
 
25
25
 
26
26
  # check if .add_direct_access file exists, if not then add direct access and create .add_direct_access file
27
- check_direct_access(::DTK::Client::Configurator.check_direct_access)
27
+ resolve_direct_access(::DTK::Client::Configurator.check_direct_access)
28
28
  entries = []
29
29
 
30
30
  if ARGV.size > 0
data/bin/dtk-shell CHANGED
@@ -10,6 +10,6 @@ trap("INT", "SIG_IGN")
10
10
  ::DTK::Client::Configurator.create_missing_clone_dirs
11
11
 
12
12
  # check if .add_direct_access file exists, if not then add direct access and create .add_direct_access file
13
- check_direct_access(::DTK::Client::Configurator.check_direct_access)
13
+ resolve_direct_access(::DTK::Client::Configurator.check_direct_access)
14
14
 
15
15
  run_shell_command()
@@ -1,5 +1,6 @@
1
1
  require 'fileutils'
2
2
  dtk_require("../domain/git_adapter")
3
+ dtk_require("../domain/git_error_handler")
3
4
 
4
5
  module DTK; module Client; class CommandHelper
5
6
  class GitRepo < self; class << self
@@ -18,15 +19,15 @@ module DTK; module Client; class CommandHelper
18
19
  begin
19
20
  GitAdapter.clone(repo_url, target_repo_dir, opts[:branch])
20
21
  rescue => e
22
+ # Handling Git error messages with more user friendly messages
23
+ e = GitErrorHandler.handle(e)
24
+
21
25
  #cleanup by deleting directory
22
26
  FileUtils.rm_rf(target_repo_dir) if File.directory?(target_repo_dir)
23
27
  error_msg = "Clone to directory (#{target_repo_dir}) failed"
24
28
 
25
- # additional data about this exception
26
- if DTK::Configuration.get(:development_mode)
27
- DtkLogger.instance.error_pp(e.message, e.backtrace)
28
- end
29
-
29
+ DtkLogger.instance.error_pp(e.message, e.backtrace)
30
+
30
31
  raise ErrorUsage.new(error_msg,:log_error=>false)
31
32
  end
32
33
  {"module_directory" => target_repo_dir}
@@ -3,7 +3,7 @@ module DTK; module Client
3
3
  def self.update_ssh_known_hosts(server_dns,server_fingerprint)
4
4
  known_hosts_path = ssh_known_hosts_path()
5
5
  if File.file?(known_hosts_path)
6
- `ssh-keygen -f #{known_hosts_path} -R #{server_dns}`
6
+ `ssh-keygen -f #{known_hosts_path} -R #{server_dns} 2> /dev/null`
7
7
  File.open(known_hosts_path,"a"){|f|f << server_fingerprint}
8
8
  else
9
9
  ssh_base_dir = ssh_base_dir()
@@ -476,16 +476,22 @@ module DTK::Client
476
476
 
477
477
  def info_aux(context_params)
478
478
  assembly_or_workspace_id, node_id, component_id, attribute_id = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID, :node_id, :component_id, :attribute_id],method_argument_names)
479
+ is_json_return = context_params.get_forwarded_option(:json_return) || false
479
480
 
480
481
  post_body = {
481
482
  :assembly_id => assembly_or_workspace_id,
482
483
  :node_id => node_id,
483
484
  :component_id => component_id,
484
485
  :attribute_id => attribute_id,
485
- :subtype => :instance
486
+ :subtype => :instance,
487
+ :json_return => is_json_return
486
488
  }
487
489
 
488
490
  resp = post rest_url("assembly/info"), post_body
491
+
492
+ # if waiting for json response we do not need to render rest of data
493
+ return resp if is_json_return
494
+
489
495
  if (component_id.nil? && !node_id.nil?)
490
496
  resp.render_workspace_node_info("node")
491
497
  elsif (component_id && node_id)
@@ -715,6 +721,74 @@ module DTK::Client
715
721
  response.render_table(:netstat_data)
716
722
  end
717
723
 
724
+ def execute_tests_aux(context_params)
725
+ execute_test_tries = 6
726
+ execute_test_sleep = 0.5
727
+
728
+ assembly_or_workspace_id,node_id = context_params.retrieve_arguments([REQ_ASSEMBLY_OR_WS_ID,:node_id],method_argument_names)
729
+
730
+ #Get list of components on particular node
731
+ post_body = {
732
+ :assembly_id => assembly_or_workspace_id,
733
+ :node_id => node_id,
734
+ :subtype => "instance",
735
+ :about => "components"
736
+ }
737
+
738
+ response = post(rest_url("assembly/info_about"),post_body)
739
+
740
+ components = []
741
+
742
+ if !response['data'].nil?
743
+ response['data'].each do |c|
744
+ components << c['display_name']
745
+ end
746
+ end
747
+
748
+ post_body = {
749
+ :assembly_id => assembly_or_workspace_id,
750
+ :node_id => node_id,
751
+ :components => components
752
+ }
753
+
754
+ response = post(rest_url("assembly/initiate_execute_tests"),post_body)
755
+ return response unless response.ok?
756
+
757
+ action_results_id = response.data(:action_results_id)
758
+ end_loop, response, count, ret_only_if_complete = false, nil, 0, true
759
+
760
+ until end_loop do
761
+ post_body = {
762
+ :action_results_id => action_results_id,
763
+ :return_only_if_complete => ret_only_if_complete,
764
+ :disable_post_processing => false,
765
+ :sort_key => "module_name"
766
+ }
767
+ response = post(rest_url("assembly/get_action_results"),post_body)
768
+ count += 1
769
+ if count > execute_test_tries or response.data(:is_complete)
770
+ end_loop = true
771
+ else
772
+ #last time in loop return whetever is there
773
+ if count == execute_test_tries
774
+ ret_only_if_complete = false
775
+ end
776
+ sleep execute_test_sleep
777
+ end
778
+ end
779
+ filtered = response.data(:results)
780
+
781
+ #Filter out results per specific component
782
+ if !options["component"].nil?
783
+ filtered.reject! do |element|
784
+ element["component_name"] != options["component"]
785
+ end
786
+ end
787
+
788
+ response.set_data(*filtered)
789
+ response.render_table(:execute_tests_data)
790
+ end
791
+
718
792
  def get_ps_aux(context_params)
719
793
  get_ps_tries = 6
720
794
  get_ps_sleep = 0.5
@@ -10,14 +10,26 @@ module DTK::Client
10
10
  KEY_EXISTS_ALREADY_CONTENT = 'key exists already'
11
11
 
12
12
  no_tasks do
13
- def password_prompt(message, add_options=true)
13
+ def self.is_ssh_key_valid(path_to_key, rsa_pub_key)
14
+ unless path_to_key.include?(".pub")
15
+ raise DtkError, "[ERROR] Invalid public key file path (#{path_to_key}). Please provide valid path and try again."
16
+ end
17
+
18
+ if(rsa_pub_key.empty? || !rsa_pub_key.include?("AAAAB3NzaC1yc2EA"))
19
+ raise DtkError, "[ERROR] SSH public key (#{path_to_key}) does not have valid content. Please check your key and try again."
20
+ end
21
+ end
22
+
23
+ def password_prompt(message, add_options=true)
14
24
  begin
15
- while line = Readline.readline("#{message}: ", add_hist = false)
25
+ # while line = Readline.readline("#{message}: ", add_hist = false)
26
+ # using 'ask' from highline gem to be able to hide input for key and secret
27
+ while line = (HighLine.ask("#{message}") { |q| q.echo = false})
16
28
  raise Interrupt if line.empty?
17
29
  return line
18
30
  end
19
- rescue Interrupt => e
20
- retry
31
+ rescue Interrupt
32
+ return nil
21
33
  ensure
22
34
  puts "\n" if line.nil?
23
35
  end
@@ -35,17 +47,17 @@ module DTK::Client
35
47
  match, matched_username = nil, nil
36
48
 
37
49
  unless File.file?(path_to_key)
38
- OsUtil.put_warning "[ERROR] " ,"No ssh key file found at (#{path_to_key}). Path is wrong or it is necessary to generate the public rsa key (e.g., run `ssh-keygen -t rsa`)", :red
39
- abort
50
+ # OsUtil.put_warning "[ERROR] " ,"No ssh key file found at (#{path_to_key}). Path is wrong or it is necessary to generate the public rsa key (e.g., run `ssh-keygen -t rsa`)", :red
51
+ raise DtkError,"[ERROR] No ssh key file found at (#{path_to_key}). Path is wrong or it is necessary to generate the public rsa key (e.g., run `ssh-keygen -t rsa`)."
40
52
  end
41
53
 
42
54
  rsa_pub_key = File.open(path_to_key){|f|f.read}
55
+ is_ssh_key_valid(path_to_key, rsa_pub_key)
43
56
 
44
57
  post_body = { :rsa_pub_key => rsa_pub_key.chomp }
45
-
46
58
  post_body.merge!(:username => name.chomp) if name
47
- proper_response = nil
48
59
 
60
+ proper_response = nil
49
61
  response, key_exists_already = Account.internal_add_user_access("account/add_user_direct_access", post_body, 'service module')
50
62
 
51
63
  return response unless (response.ok? || key_exists_already)
@@ -56,7 +68,8 @@ module DTK::Client
56
68
  if response && !match
57
69
  repo_manager_fingerprint,repo_manager_dns = response.data_ret_and_remove!(:repo_manager_fingerprint,:repo_manager_dns)
58
70
  SshProcessing.update_ssh_known_hosts(repo_manager_dns,repo_manager_fingerprint)
59
- OsUtil.print("Ssh key added successfully!", :yellow)
71
+ name ||= response.data["new_username"]
72
+ OsUtil.print("SSH key '#{name}' added successfully!", :yellow)
60
73
  end
61
74
 
62
75
  return response, match, matched_username
@@ -75,16 +88,16 @@ module DTK::Client
75
88
  end
76
89
 
77
90
  3.times do
78
- old_pass_prompt = password_prompt("Enter old password")
91
+ old_pass_prompt = password_prompt("Enter old password: ")
79
92
 
80
93
  break if (old_pass.eql?(old_pass_prompt) || old_pass_prompt.nil?)
81
94
  OsUtil.print("Incorrect old password!", :yellow)
82
95
  end
83
96
  return unless old_pass.eql?(old_pass_prompt)
84
97
 
85
- new_pass_prompt = password_prompt("Enter new password")
98
+ new_pass_prompt = password_prompt("Enter new password: ")
86
99
  return if new_pass_prompt.nil?
87
- confirm_pass_prompt = password_prompt("Confirm new password")
100
+ confirm_pass_prompt = password_prompt("Confirm new password: ")
88
101
 
89
102
  if new_pass_prompt.eql?(confirm_pass_prompt)
90
103
  post_body = {:new_password => new_pass_prompt}
@@ -99,7 +112,7 @@ module DTK::Client
99
112
  end
100
113
  end
101
114
 
102
- desc "list-ssh-keys", "Show list of keys that your account profile has saved"
115
+ desc "list-ssh-keys", "Show list of key pairs that your account profile has saved"
103
116
  def list_ssh_keys(context_params)
104
117
  username = parse_key_value_file(::DTK::Client::Configurator.CRED_FILE)[:username]
105
118
  post_body = {:username => username}
@@ -108,7 +121,7 @@ module DTK::Client
108
121
  response.render_table(:account_ssh_keys)
109
122
  end
110
123
 
111
- desc "add-ssh-key NAME [PATH-TO-RSA-PUB-KEY]","Adds direct access to modules. Optional parameters is path to a ssh rsa public key and default is <user-home-dir>/.ssh/id_rsa.pub"
124
+ desc "add-ssh-key KEYPAIR-NAME [PATH-TO-RSA-PUB-KEY]","Adds a named ssh key to your user account to access modules from the catalog. Optional parameters is path to a ssh rsa public key and default is <user-home-dir>/.ssh/id_rsa.pub"
112
125
  def add_ssh_key(context_params)
113
126
  name, path_to_key = context_params.retrieve_arguments([:option_1!, :option_2],method_argument_names)
114
127
  path_to_key ||= SshProcessing.default_rsa_pub_key_path()
@@ -116,26 +129,25 @@ module DTK::Client
116
129
  response, matched, matched_username = Account.add_key(path_to_key, name)
117
130
 
118
131
  if matched
119
- DTK::Client::OsUtil.print("Provided SSH PUB key has already been added.", :yellow)
132
+ DTK::Client::OsUtil.print("Provided ssh pub key has already been added.", :yellow)
120
133
  elsif matched_username
121
134
  DTK::Client::OsUtil.print("User ('#{matched_username}') already exists.", :yellow)
122
135
  else
123
- FileUtils.touch(DTK::Client::Configurator::DIRECT_ACCESS) if response.ok?
136
+ DTK::Client::Configurator.add_current_user_to_direct_access() if response.ok?
124
137
  end
138
+
139
+ response
125
140
  end
126
141
 
127
- desc "remove-ssh-key NAME ","Removes user and direct access to modules."
128
- def remove_ssh_key(context_params)
142
+ desc "delete-ssh-key KEYPAIR-NAME ","Deletes the named ssh key from your user account"
143
+ def delete_ssh_key(context_params)
129
144
  name = context_params.retrieve_arguments([:option_1!],method_argument_names)
130
145
  post_body = {:username => name.chomp}
131
146
 
132
- response = post rest_url("component_module/remove_user_direct_access"), post_body
133
- return response unless response.ok?
134
-
135
- response = post rest_url("service_module/remove_user_direct_access"), post_body
147
+ response = post rest_url("account/remove_user_direct_access"), post_body
136
148
  return response unless response.ok?
137
149
 
138
- OsUtil.print("SSH key removed successfully!", :yellow)
150
+ OsUtil.print("Ssh key '#{name}' removed successfully!", :yellow)
139
151
  response
140
152
  end
141
153
 
@@ -356,7 +356,7 @@ TODO: might deprecate
356
356
  :desc => "DTK Repo Manager from which to resolve requested module."
357
357
  def install(context_params)
358
358
  create_missing_clone_dirs()
359
- check_direct_access(::DTK::Client::Configurator.check_direct_access)
359
+ resolve_direct_access(::DTK::Client::Configurator.check_direct_access)
360
360
  remote_module_name, version = context_params.retrieve_arguments([:option_1!, :option_2],method_argument_names)
361
361
  # in case of auto-import via service import, we skip cloning to speed up a process
362
362
  skip_cloning = context_params.get_forwarded_options()['skip_cloning'] if context_params.get_forwarded_options()
@@ -2,6 +2,9 @@ dtk_require_common_commands('thor/task_status')
2
2
  dtk_require_common_commands('thor/set_required_params')
3
3
  module DTK::Client
4
4
  class Node < CommandBaseThor
5
+
6
+ include AssemblyWorkspaceMixin
7
+
5
8
  no_tasks do
6
9
  include TaskStatusMixin
7
10
  include SetRequiredParamsMixin
@@ -73,15 +76,58 @@ module DTK::Client
73
76
 
74
77
  desc "NODE-NAME/ID info","Info about node"
75
78
  def info(context_params)
76
-
77
79
  node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
78
80
  post_body = {
79
81
  :node_id => node_id,
80
82
  :subtype => 'instance',
81
83
  }
84
+
82
85
  post rest_url("node/info"), post_body
83
86
  end
84
87
 
88
+ desc "NODE-NAME/ID ssh [--keypair] [--remote-user]","SSH into node, optional parameters are path to keypair and remote user."
89
+ method_option "--keypair",:type => :string, :desc => "Keypair used for connection, if not provided default is used", :banner => "KEYPAIR"
90
+ method_option "--remote-user",:type => :string, :desc => "Remote user used for connection", :banner => "REMOTE USER"
91
+ def ssh(context_params)
92
+ if OsUtil.is_windows?
93
+ puts "[NOTICE] SSH functionality is currenly not supported on Windows."
94
+ return
95
+ end
96
+
97
+ node_id = context_params.retrieve_arguments([:node_id!],method_argument_names)
98
+
99
+
100
+ keypair_location = options.keypair || OsUtil.dtk_keypair_location()
101
+
102
+
103
+ remote_user = options.send('remote-user') || 'ubuntu'
104
+
105
+ unless File.exists?(keypair_location||'')
106
+ error_message = keypair_location ? "Not able to find keypair, '#{keypair_location}'" : "Default keypair not set, please provide one in 'ssh' command"
107
+ raise ::DTK::Client::DtkError, error_message
108
+ end
109
+
110
+ context_params.forward_options({ :json_return => true })
111
+ response = info_aux(context_params)
112
+
113
+
114
+ if response.ok?
115
+ node_info = response.data['nodes'].find { |n| node_id == n['node_id'] }
116
+ public_dns = node_info ? node_info['external_ref']['ec2_public_address'] : nil
117
+
118
+ raise ::DTK::Client::DtkError, "Not able to resolve instance address, has instance been stopped?" unless public_dns
119
+
120
+ connection_string = "#{remote_user}@#{public_dns}"
121
+ ssh_command = "ssh -o \"StrictHostKeyChecking no\" -o \"UserKnownHostsFile /dev/null\" -i #{keypair_location} #{connection_string}"
122
+
123
+ OsUtil.print("You are entering SSH terminal (#{connection_string}) ...", :yellow)
124
+ Kernel.system(ssh_command)
125
+ OsUtil.print("You are leaving SSH terminal, and returning to DTK Shell ...", :yellow)
126
+ else
127
+ return response
128
+ end
129
+ end
130
+
85
131
  desc "NODE-NAME/ID list-components","List components that are on the node instance."
86
132
  method_option :list, :type => :boolean, :default => false
87
133
  def list_components(context_params)
@@ -140,6 +140,7 @@ TODO: overlaps with different meaning
140
140
  ['list-components',"list-components","# List components."]
141
141
  ],
142
142
  :utils => [
143
+ ['execute-tests',"execute-tests [--component COMPONENT-NAME]","# Execute tests. --component filters results per component."],
143
144
  ['get-netstats',"get-netstats","# Get netstats."],
144
145
  ['get-ps',"get-ps [--filter PATTERN]","# Get ps."],
145
146
  ['grep',"grep LOG-PATH NODE-ID-PATTERN GREP-PATTERN [--first]","# Grep log from multiple nodes. --first option returns first match (latest log entry)."],
@@ -156,7 +157,8 @@ TODO: overlaps with different meaning
156
157
  ['list-components',"list-components","# List components associated with service's node."],
157
158
  ['set-attribute',"set-attribute ATTRIBUTE-NAME [VALUE] [-u]","# (Un)Set attribute value. The option -u will unset the attribute's value."],
158
159
  ['start', "start", "# Start node instance."],
159
- ['stop', "stop", "# Stop node instance."]
160
+ ['stop', "stop", "# Stop node instance."],
161
+ ['ssh', "ssh [--keypair] [--remote-user]", "# SSH into node, optional parameters are path to keypair and remote user."]
160
162
  ],
161
163
  :component => [
162
164
  ['info',"info","# Return info about component instance belonging to given node."],
@@ -632,6 +634,13 @@ TODO: will put in dot release and will rename to 'extend'
632
634
  get_netstats_aux(context_params)
633
635
  end
634
636
 
637
+ # using HIDE_FROM_BASE to hide this command from base context (dtk:/assembly>)
638
+ desc "HIDE_FROM_BASE execute-tests [--component COMPONENT-NAME]", "Execute tests. --component filters results per component"
639
+ method_option :component, :type => :string, :desc => "Component name"
640
+ def execute_tests(context_params)
641
+ execute_tests_aux(context_params)
642
+ end
643
+
635
644
  # using HIDE_FROM_BASE to hide this command from base context (dtk:/assembly>)
636
645
  desc "HIDE_FROM_BASE get-ps [--filter PATTERN]", "Get ps"
637
646
  method_option :filter, :type => :boolean, :default => false, :aliases => '-f'
@@ -193,7 +193,7 @@ module DTK::Client
193
193
  method_option :ignore, :aliases => '-i', :type => :boolean, :default => false
194
194
  def install(context_params)
195
195
  create_missing_clone_dirs()
196
- check_direct_access(::DTK::Client::Configurator.check_direct_access)
196
+ resolve_direct_access(::DTK::Client::Configurator.check_direct_access)
197
197
  remote_module_name = context_params.retrieve_arguments([:option_1!],method_argument_names)
198
198
  ignore_component_error = options.ignore?
199
199
 
@@ -116,6 +116,7 @@ module DTK::Client
116
116
  ['list-components',"list-components","# List components."]
117
117
  ],
118
118
  :utils => [
119
+ ['execute-tests',"execute-tests [--component COMPONENT-NAME]","# Execute tests. --component filters results per component."],
119
120
  ['get-netstats',"get-netstats","# Get netstats."],
120
121
  ['get-ps',"get-ps [--filter PATTERN]","# Get ps."],
121
122
  ['grep',"grep LOG-PATH NODE-ID-PATTERN GREP-PATTERN [--first]","# Grep log from multiple nodes. --first option returns first match (latest log entry)."],
@@ -132,7 +133,8 @@ module DTK::Client
132
133
  ['list-components',"list-components","# List components associated with workspace's node."],
133
134
  ['set-attribute',"set-attribute ATTRIBUTE-NAME [VALUE] [-u]","# (Un)Set attribute value. The option -u will unset the attribute's value."],
134
135
  ['start', "start", "# Start node instance."],
135
- ['stop', "stop", "# Stop node instance."]
136
+ ['stop', "stop", "# Stop node instance."],
137
+ ['ssh', "ssh [--keypair] [--remote-user]", "# SSH into node, optional parameters are path to keypair and remote user."]
136
138
  ],
137
139
  :component => [
138
140
  ['info',"info","# Return info about component instance belonging to given node."],
@@ -311,6 +313,13 @@ module DTK::Client
311
313
  get_netstats_aux(context_params)
312
314
  end
313
315
 
316
+ # using HIDE_FROM_BASE to hide this command from base context (dtk:/workspace>)
317
+ desc "HIDE_FROM_BASE execute-tests [--component COMPONENT-NAME]", "Execute tests. --component filters results per component"
318
+ method_option :component, :type => :string, :desc => "Component name"
319
+ def execute_tests(context_params)
320
+ execute_tests_aux(context_params)
321
+ end
322
+
314
323
  # using HIDE_FROM_BASE to hide this command from base context (dtk:/workspace>)
315
324
  desc "HIDE_FROM_BASE get-ps [--filter PATTERN]", "Get ps"
316
325
  method_option :filter, :type => :boolean, :default => false, :aliases => '-f'
data/lib/configurator.rb CHANGED
@@ -6,12 +6,12 @@ module DTK
6
6
  module Client
7
7
  class Configurator
8
8
 
9
- CONFIG_FILE = File.join(OsUtil.dtk_local_folder, "client.conf")
9
+ CONFIG_FILE = File.join(OsUtil.dtk_local_folder, "client.conf")
10
10
  CRED_FILE = File.join(OsUtil.dtk_local_folder, ".connection")
11
11
  DIRECT_ACCESS = File.join(OsUtil.dtk_local_folder, ".add_direct_access")
12
12
 
13
- require 'fileutils'
14
- FileUtils.mkdir(OsUtil.dtk_local_folder) unless File.directory?(OsUtil.dtk_local_folder)
13
+ require 'fileutils'
14
+ FileUtils.mkdir(OsUtil.dtk_local_folder) unless File.directory?(OsUtil.dtk_local_folder)
15
15
 
16
16
  def self.CONFIG_FILE
17
17
  CONFIG_FILE
@@ -44,10 +44,10 @@ module DTK
44
44
 
45
45
  # return true/false, .add_direct_access file location and ssk key file location
46
46
  def self.check_direct_access
47
- file_exists = File.exists?(DIRECT_ACCESS)
47
+ username_exists = check_for_username_entry(client_username())
48
48
  ssh_key_path = SshProcessing.default_rsa_pub_key_path()
49
49
 
50
- {:file_exists => file_exists, :file_path => DIRECT_ACCESS, :ssh_key_path => ssh_key_path}
50
+ {:username_exists => username_exists, :file_path => DIRECT_ACCESS, :ssh_key_path => ssh_key_path}
51
51
  end
52
52
 
53
53
  def self.generate_conf_file(file_path, properties, header)
@@ -86,6 +86,53 @@ module DTK
86
86
  FileUtils.mkdir(OsUtil.module_clone_location) unless File.directory?(OsUtil.module_clone_location)
87
87
  FileUtils.mkdir(OsUtil.service_clone_location) unless File.directory?(OsUtil.service_clone_location)
88
88
  end
89
+
90
+
91
+ def self.parse_key_value_file(file)
92
+ #adapted from mcollective config
93
+ ret = Hash.new
94
+ raise DTK::Client::DtkError,"Config file (#{file}) does not exists" unless File.exists?(file)
95
+ File.open(file).each do |line|
96
+ # strip blank spaces, tabs etc off the end of all lines
97
+ line.gsub!(/\s*$/, "")
98
+ unless line =~ /^#|^$/
99
+ if (line =~ /(.+?)\s*=\s*(.+)/)
100
+ key = $1
101
+ val = $2
102
+ ret[key.to_sym] = val
103
+ end
104
+ end
105
+ end
106
+ ret
107
+ end
108
+ def self.add_current_user_to_direct_access()
109
+ username = client_username()
110
+
111
+ File.open(DIRECT_ACCESS, 'a') do |file|
112
+ file.puts(username)
113
+ end
114
+
115
+ true
116
+ end
117
+
118
+ def self.client_username()
119
+ parse_key_value_file(CRED_FILE)[:username]
120
+ end
121
+
122
+ #
123
+ # Method will check if there is username entry in DIRECT_ACCESS file
124
+ #
125
+ def self.check_for_username_entry(username)
126
+ if File.exists?(DIRECT_ACCESS)
127
+ File.open(DIRECT_ACCESS).each do |line|
128
+ if line.strip.eql?(username)
129
+ return true
130
+ end
131
+ end
132
+ end
133
+
134
+ return false
135
+ end
89
136
  end
90
137
  end
91
138
  end
data/lib/core.rb CHANGED
@@ -111,24 +111,25 @@ def validate_connection(connection)
111
111
  end
112
112
 
113
113
  # check if .add_direct_access file exists, if not then add direct access and create .add_direct_access file
114
- def check_direct_access(params)
115
- return if params[:file_exists]
114
+ def resolve_direct_access(params)
115
+ return if params[:username_exists]
116
116
 
117
117
  puts "Adding direct access for current user..."
118
118
  # response = DTK::Client::Account.add_access(params[:ssh_key_path])
119
119
  response, matched_pub_key, matched_username = DTK::Client::Account.add_key(params[:ssh_key_path])
120
120
 
121
121
  if !response.ok?
122
- DTK::Client::OsUtil.print("We were not able to add direct access for current user, server error '#{response.error_message}'. In order to properly use dtk-shell you will have to add access manually ('dtk account add-ssh-key').\n", :yellow)
122
+ DTK::Client::OsUtil.print("We were not able to add direct access for current user. #{response.error_message}. In order to properly use dtk-shell you will have to add access manually ('dtk account add-ssh-key').\n", :yellow)
123
123
  elsif matched_pub_key
124
124
  # message will be displayed by add key # TODO: Refactor this flow
125
125
  DTK::Client::OsUtil.print("Provided SSH PUB key has already been added.", :yellow)
126
- FileUtils.touch(params[:file_path])
126
+ DTK::Client::Configurator.add_current_user_to_direct_access()
127
127
  elsif matched_username
128
128
  DTK::Client::OsUtil.print("User with provided name already exists.", :yellow)
129
129
  else
130
- DTK::Client::OsUtil.print("Your SSH PUB key has been successfully added.", :yellow)
131
- FileUtils.touch(params[:file_path])
130
+ # commented out because 'add_key' method called above will also print the same message
131
+ # DTK::Client::OsUtil.print("Your SSH PUB key has been successfully added.", :yellow)
132
+ DTK::Client::Configurator.add_current_user_to_direct_access()
132
133
  end
133
134
 
134
135
 
@@ -218,22 +219,9 @@ module DTK
218
219
  module ParseFile
219
220
 
220
221
  def parse_key_value_file(file)
221
- #adapted from mcollective config
222
- ret = Hash.new
223
- raise DTK::Client::DtkError,"Config file (#{file}) does not exists" unless File.exists?(file)
224
- File.open(file).each do |line|
225
- # strip blank spaces, tabs etc off the end of all lines
226
- line.gsub!(/\s*$/, "")
227
- unless line =~ /^#|^$/
228
- if (line =~ /(.+?)\s*=\s*(.+)/)
229
- key = $1
230
- val = $2
231
- ret[key.to_sym] = val
232
- end
233
- end
234
- end
235
- ret
222
+ DTK::Client::Configurator.parse_key_value_file(file)
236
223
  end
224
+
237
225
  end
238
226
  class Config < Hash
239
227
  include Singleton
@@ -270,6 +258,7 @@ module DTK
270
258
  missing_keys = REQUIRED_KEYS - keys
271
259
  raise DTK::Client::DtkError,"Missing config keys (#{missing_keys.join(",")}). Please check your configuration file #{CONFIG_FILE} for required keys!" unless missing_keys.empty?
272
260
  end
261
+
273
262
  end
274
263
 
275
264
 
@@ -18,10 +18,13 @@ module DTK
18
18
  @git_repo.add(untracked())
19
19
  @git_repo.add(added())
20
20
  @git_repo.add(changed())
21
- deleted().each do |file, status|
22
- # this indicates that change has not been staged
23
- if status.stage
21
+ deleted().each do |file|
22
+ begin
24
23
  @git_repo.remove(file)
24
+ rescue
25
+ # ignore this error means file has already been staged
26
+ # we cannot support status of file, in 1.8.7 so this is
27
+ # solution for that
25
28
  end
26
29
  end
27
30
  end
@@ -0,0 +1,45 @@
1
+
2
+ module DTK
3
+ module Client
4
+
5
+ class GitHandledException < Exception
6
+ def initialize(msg, backtrace)
7
+ super(msg)
8
+ set_backtrace(backtrace)
9
+ end
10
+ end
11
+
12
+ class GitErrorHandler
13
+
14
+ # due to problems with git logging messages which are not user friendly we are going to wrap their error and try to produce more readable results
15
+ def self.handle(exception)
16
+ handled_exception = exception
17
+
18
+ if exception.is_a? Git::GitExecuteError
19
+ error_message = user_friendly_message(exception.message)
20
+ handled_exception = GitHandledException.new(error_message, exception.backtrace)
21
+ end
22
+
23
+ handled_exception
24
+ end
25
+
26
+ private
27
+
28
+ def self.user_friendly_message(message)
29
+ case message
30
+ when /repository not found/i
31
+ "Repository not found"
32
+ when /repository (.*) not found/i
33
+ "Repository #{$1.strip()} not found"
34
+ when /destination path (.*) already exists/i
35
+ "Destination folder #{$1.strip()} already exists"
36
+ when /Authentication failed for (.*)$/i
37
+ "Authentication failed for given repository #{$1.strip()}"
38
+ else
39
+ message
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
- module DtkClient
2
- VERSION="0.5.9"
3
- end
1
+ module DtkClient
2
+ VERSION="0.5.10"
3
+ end
data/lib/dtk_logger.rb CHANGED
@@ -61,14 +61,14 @@ class DtkLogger
61
61
  @logger.error(log_text) if log_created?
62
62
  end
63
63
 
64
- def error_pp(message, backtrace)
65
- error(message, true)
64
+ def error_pp(message, backtrace, sttdout_out = true)
65
+ error(message, sttdout_out)
66
66
  # we do not print this to STDOUT (will be overriden with DEVELOPMENT_MODE)
67
67
  error(PP.pp(backtrace, ""), false) if backtrace
68
68
  end
69
69
 
70
- def fatal_pp(message, backtrace)
71
- fatal(message, true)
70
+ def fatal_pp(message, backtrace, sttdout_out = true)
71
+ fatal(message, sttdout_out)
72
72
  # we do not print this to STDOUT (will be overriden with DEVELOPMENT_MODE)
73
73
  fatal(PP.pp(backtrace, ""), false) if backtrace
74
74
  end
@@ -25,8 +25,8 @@ module DTK
25
25
 
26
26
  @@cached_response = {}
27
27
  @@invalidate_map = []
28
- TIME_DIFF = 60 #second(s)
29
- EXTENDED_TIMEOUT = 360 #second(s)
28
+ TIME_DIFF = 60 # second(s)
29
+ EXTENDED_TIMEOUT = 360 # second(s)
30
30
  HIDE_FROM_BASE_CONTEXT = "HIDE_FROM_BASE"
31
31
 
32
32
  # thor command specific constants
@@ -289,40 +289,6 @@ module DTK
289
289
  end
290
290
  end
291
291
  end
292
-
293
- # will leave this commented for now until we check if new code works properly
294
- # if children
295
- # current_children = []
296
- # children.each do |child|
297
- # current_children << child.to_s
298
-
299
- # # create entry e.g. assembly_node_id
300
- # child_id_sym = (command.downcase + '_' + current_children.join('_') + '_wid').to_sym
301
-
302
- # # n-context matching
303
- # matched_data = task[1].usage.match(/\[?#{child.to_s.upcase}.?(NAME\/ID|ID\/NAME|ID|NAME)(\-?PATTERN)?\]?/)
304
- # if matched_data
305
- # cached_tasks[child_id_sym] = cached_tasks.fetch(child_id_sym,[]) << task_name
306
- # end
307
-
308
- # # override method list, we add these methods only once
309
- # if override_task_obj && !override_task_obj.is_completed?(child)
310
- # command_o_tasks, identifier_o_tasks = override_task_obj.get_all_tasks(child)
311
- # child_sym = (command.downcase + '_' + current_children.join('_')).to_sym
312
-
313
- # command_o_tasks.each do |o_task|
314
- # cached_tasks[child_sym] = cached_tasks.fetch(child_sym,[]) << o_task[0]
315
- # end
316
-
317
- # identifier_o_tasks.each do |o_task|
318
- # cached_tasks[child_id_sym] = cached_tasks.fetch(child_id_sym,[]) << o_task[0]
319
- # end
320
-
321
- # override_task_obj.add_to_completed(child)
322
- # end
323
- # end
324
- # end
325
-
326
292
  end
327
293
  end
328
294
 
@@ -482,6 +448,14 @@ module DTK
482
448
  return basename
483
449
  end
484
450
 
451
+ #
452
+ # Returns list of invisible contexts with sufix provided (if any)
453
+ #
454
+
455
+ def self.invisible_context_list(sufix = 'identifier')
456
+ self.respond_to?(:invisible_context) ? self.invisible_context.collect { |i| "#{i}-#{sufix}" } : []
457
+ end
458
+
485
459
  desc "help [SUBCOMMAND]", "Describes available subcommands or one specific subcommand"
486
460
  def help(*args)
487
461
  puts # pretty print
data/lib/shell/context.rb CHANGED
@@ -740,7 +740,7 @@ module DTK
740
740
  opts[id_label] = id
741
741
 
742
742
  response_ruby_obj = DTK::Client::CommandBaseThor.get_cached_response(endpoint.to_sym, url, opts)
743
- return [] unless response_ruby_obj.ok?
743
+ return [] if(response_ruby_obj.nil? || !response_ruby_obj.ok?)
744
744
 
745
745
  response_ruby_obj.data.each do |d|
746
746
  candidates << d["display_name"]
@@ -840,7 +840,7 @@ module DTK
840
840
  clazz = Context.get_command_class(entity_name)
841
841
  current_context_command = active_context_copy.last_command_name
842
842
 
843
- if (current_context_command != entity_name)
843
+ if ((current_context_command != entity_name) && !current_context_command.eql?("utils"))
844
844
  current_context_clazz = Context.get_command_class(current_context_command)
845
845
  options = Context.get_thor_options(current_context_clazz, cmd) unless current_context_command.nil?
846
846
  else
data/lib/shell/domain.rb CHANGED
@@ -24,6 +24,10 @@ module DTK
24
24
  @thor_options
25
25
  end
26
26
 
27
+ def get_forwarded_option(key)
28
+ @thor_options ? @thor_options[key] : nil
29
+ end
30
+
27
31
  def get_forwarded_thor_option(option_key)
28
32
  return @thor_options ? @thor_options[option_key] : nil
29
33
  end
@@ -79,6 +83,16 @@ module DTK
79
83
  id = matched[1].to_i - 1
80
84
  element = @method_arguments[id]
81
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
+
82
96
  unless method_info.empty?
83
97
  unless element
84
98
  errors << method_info[id] if required
@@ -215,6 +215,16 @@ class Thor
215
215
  # monkey patching here => END
216
216
  shell.print_table(list, :indent => 2, :truncate => true)
217
217
  shell.say
218
+
219
+ # print sub context information
220
+ # if @@shell_context && @@shell_context.active_context.current_identifier?
221
+ # sub_children = self.respond_to?(:valid_children) ? self.valid_children() : []
222
+ # sub_children += self.invisible_context_list()
223
+
224
+ # shell.say(" Change context (cc) to: #{sub_children.join(', ')}", :BOLD) unless sub_children.empty?
225
+ # shell.say
226
+ # end
227
+
218
228
  class_options_help(shell)
219
229
  end
220
230
  end
@@ -1,5 +1,6 @@
1
1
  require 'colorize'
2
2
  require 'readline'
3
+ require 'highline/import'
3
4
 
4
5
  module DTK
5
6
  module Shell
@@ -100,7 +101,9 @@ module DTK
100
101
  prompt_input = ">> "
101
102
  end
102
103
 
103
- while line = Readline.readline(prompt_input, true)
104
+ # while line = Readline.readline(prompt_input, true)
105
+ #using 'ask' from highline gem to be able to hide input for key and secret
106
+ while line = ask("#{prompt_input}") { |q| q.echo = false}
104
107
  if is_required && line.empty?
105
108
  puts INVALID_INPUT
106
109
  next
data/lib/util/os_util.rb CHANGED
@@ -9,6 +9,8 @@ module DTK
9
9
 
10
10
  extend Auxiliary
11
11
 
12
+ DTK_KEYPAIR = 'dtk.pem'
13
+
12
14
  class << self
13
15
  def is_mac?
14
16
  RUBY_PLATFORM.downcase.include?('darwin')
@@ -147,6 +149,18 @@ module DTK
147
149
  # remove last slash if set in configuration by mistake
148
150
  final_path.gsub(/\/$/,'')
149
151
  end
152
+
153
+ #
154
+ # Checks to find dtk.pem in configuration node, if not found displays tip message
155
+ #
156
+ def dtk_keypair_location()
157
+ path_to_keypair = "#{dtk_local_folder}#{DTK_KEYPAIR}"
158
+ return path_to_keypair if File.exists?(path_to_keypair)
159
+ print("TIP: You can save your keypair as '#{path_to_keypair}' and it will be used as default keypair.", :yellow)
160
+ nil
161
+ end
162
+
163
+
150
164
  private :clone_base_path
151
165
  #
152
166
  #
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.9
4
+ version: 0.5.10
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-03-06 00:00:00.000000000 Z
11
+ date: 2014-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -249,6 +249,7 @@ files:
249
249
  - lib/context_router.rb
250
250
  - lib/core.rb
251
251
  - lib/domain/git_adapter.rb
252
+ - lib/domain/git_error_handler.rb
252
253
  - lib/domain/response.rb
253
254
  - lib/dtk-client/version.rb
254
255
  - lib/dtk_constants.rb
@@ -325,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
325
326
  version: '0'
326
327
  requirements: []
327
328
  rubyforge_project:
328
- rubygems_version: 2.1.9
329
+ rubygems_version: 2.1.5
329
330
  signing_key:
330
331
  specification_version: 4
331
332
  summary: DTK CLI client for DTK server interaction.