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 +8 -8
- data/bin/dtk +1 -1
- data/bin/dtk-shell +1 -1
- data/lib/command_helpers/git_repo.rb +6 -5
- data/lib/command_helpers/ssh_processing.rb +1 -1
- data/lib/commands/common/thor/assembly_workspace.rb +75 -1
- data/lib/commands/thor/account.rb +35 -23
- data/lib/commands/thor/component_module.rb +1 -1
- data/lib/commands/thor/node.rb +47 -1
- data/lib/commands/thor/service.rb +10 -1
- data/lib/commands/thor/service_module.rb +1 -1
- data/lib/commands/thor/workspace.rb +10 -1
- data/lib/configurator.rb +52 -5
- data/lib/core.rb +10 -21
- data/lib/domain/git_adapter.rb +6 -3
- data/lib/domain/git_error_handler.rb +45 -0
- data/lib/dtk-client/version.rb +3 -3
- data/lib/dtk_logger.rb +4 -4
- data/lib/parser/adapters/thor.rb +10 -36
- data/lib/shell/context.rb +2 -2
- data/lib/shell/domain.rb +14 -0
- data/lib/shell/help_monkey_patch.rb +10 -0
- data/lib/shell/interactive_wizard.rb +4 -1
- data/lib/util/os_util.rb +14 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDEyNmM1MGE3NzA2MzQ5OGMyMzhhNDVjZDUxY2JkMmE0MTYxNDFkYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWRiODEwOTRkYjNkZDRhNzI4ZjNmNjVjZmQ3ODQwMmI1Y2VjMTQwNQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjE1MzUwZTNlZTMzMWY3OTRkMWJhNGJmNDQyZjU2YTM2YjkwYWFhZjczZjRh
|
10
|
+
ODY2NTVjOTI5M2Y2YzVkYjFhMzlhMmYzMTcwZDZiZmNjZDNmM2VhZWIzZGY3
|
11
|
+
MzMyYzBlZDM3ZDQxNjVlOGQ4MjYzNmY3ZWEwMmE1OTIxYjkzNDY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
26
|
-
|
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
|
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
|
20
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
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 "
|
128
|
-
def
|
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("
|
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("
|
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
|
-
|
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()
|
data/lib/commands/thor/node.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
47
|
+
username_exists = check_for_username_entry(client_username())
|
48
48
|
ssh_key_path = SshProcessing.default_rsa_pub_key_path()
|
49
49
|
|
50
|
-
{:
|
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
|
115
|
-
return if params[:
|
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
|
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
|
-
|
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
|
-
|
131
|
-
|
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
|
-
|
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
|
|
data/lib/domain/git_adapter.rb
CHANGED
@@ -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
|
22
|
-
|
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
|
data/lib/dtk-client/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module DtkClient
|
2
|
-
VERSION="0.5.
|
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,
|
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,
|
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
|
data/lib/parser/adapters/thor.rb
CHANGED
@@ -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 []
|
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.
|
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-
|
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.
|
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.
|