dtk-client 0.10.4 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cli/command/account/add_ssh_key.rb +0 -1
  3. data/lib/cli/command/account/delete_ssh_key.rb +0 -1
  4. data/lib/cli/command/module/delete_from_remote.rb +7 -1
  5. data/lib/cli/command/module/pull_dtkn.rb +10 -2
  6. data/lib/cli/runner.rb +24 -3
  7. data/lib/cli/version.rb +1 -1
  8. data/lib/client/config/default.conf +0 -2
  9. data/lib/client/conn.rb +14 -7
  10. data/lib/client/error/subclasses.rb +1 -1
  11. data/lib/client/git_repo/adapter/git_gem.rb +58 -3
  12. data/lib/client/git_repo.rb +23 -0
  13. data/lib/client/load_source/component_info.rb +4 -2
  14. data/lib/client/load_source/service_info.rb +4 -2
  15. data/lib/client/load_source.rb +5 -0
  16. data/lib/client/operation/client_module_dir/git_repo/internal/dtkn.rb +5 -0
  17. data/lib/client/operation/client_module_dir/git_repo/internal.rb +50 -13
  18. data/lib/client/operation/client_module_dir/git_repo.rb +50 -4
  19. data/lib/client/operation/client_module_dir.rb +1 -2
  20. data/lib/client/operation/module/delete_from_remote.rb +2 -1
  21. data/lib/client/operation/module/install/dependent_modules/component_dependency_tree.rb +8 -0
  22. data/lib/client/operation/module/install/dependent_modules/component_module.rb +6 -7
  23. data/lib/client/operation/module/install/dependent_modules.rb +7 -1
  24. data/lib/client/operation/module/install/print_helper.rb +12 -0
  25. data/lib/client/operation/module/pull_dtkn.rb +55 -6
  26. data/lib/client/operation/module/push.rb +0 -2
  27. data/lib/client/operation/module/push_dtkn/convert_source/component_info.rb +1 -0
  28. data/lib/client/operation/module/push_dtkn/convert_source/service_info.rb +1 -0
  29. data/lib/client/operation/module/push_dtkn/convert_source.rb +39 -22
  30. data/lib/client/operation/service/ssh.rb +1 -1
  31. data/lib/client/session.rb +4 -1
  32. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43813c96b0c40e8459d6668ca71bd0b8db38958f
4
- data.tar.gz: ab8249e25eb9242e7b09f45b68b834e5c059764c
3
+ metadata.gz: 770b6fa7ab8687c5275c4acce3eaa5cae52a330c
4
+ data.tar.gz: 745309e408b3d4fa06175f4cdb82d665afd22c7b
5
5
  SHA512:
6
- metadata.gz: 4dbb96de07e1c8ca3f6721b15151196e91f52444b002aef643fedd7aad32e494d2db00d499a807abc474909d7374d1256861fe90b03e2d1ad8a63e9d665651ba
7
- data.tar.gz: abc0b3255033efc1ad9ee47e99eab523e25f4226732ae837de6c36cb1b9bbe99dd696d021ee18f46aa4518392f09997cb83aa809c283eb3040d6ee4f629fba85
6
+ metadata.gz: 5d614db5a69af9d464e21ec16f4c78209e2061c3dbd97c2b4890928c87b457aa5d2822860c3ae3c27c97b29889b729ea96199ac34b2390878989450f121f4881
7
+ data.tar.gz: 8be6f20053599b04e50d144b7de3b8a58a6f5cb9e5c0cd6de8fcdea60d39c86cf5045d8da5e6c529e0024ce177edbd34ab686472d55b719c35ff7b1d2da9c7a3
@@ -21,7 +21,6 @@ module DTK::Client
21
21
  subcommand_def 'add-ssh-key' do |c|
22
22
  c.arg Token::Arg.keypair_name
23
23
  command_body c, 'add-ssh-key', 'Adds SSH key for current user' do |sc|
24
- sc.flag Token.directory_path
25
24
  sc.action do |_global_options, options, args|
26
25
  directory_path = options[:directory_path]
27
26
  name = args[0]
@@ -21,7 +21,6 @@ module DTK::Client
21
21
  subcommand_def 'delete-ssh-key' do |c|
22
22
  c.arg Token::Arg.keypair_name
23
23
  command_body c, 'delete-ssh-key', 'Deletes SSH key for current user' do |sc|
24
- sc.flag Token.directory_path
25
24
  sc.switch Token.skip_prompt
26
25
  sc.action do |_global_options, options, args|
27
26
  skip_prompt = options[:skip_prompt]
@@ -23,10 +23,16 @@ module DTK::Client
23
23
  command_body c, 'delete-from-remote', 'Delete module from the DTK remote catalog (DTKN)' do |sc|
24
24
  sc.flag Token.version
25
25
  sc.switch Token.skip_prompt
26
+ sc.switch Token.force
26
27
 
27
28
  sc.action do |_global_options, options, args|
28
29
  module_ref = module_ref_object_from_options_or_context?(:module_ref => args[0], :version => options[:version])
29
- Operation::Module.delete_from_remote(:module_ref => module_ref, :skip_prompt => options[:skip_prompt])
30
+ operation_args = {
31
+ :module_ref => module_ref,
32
+ :skip_prompt => options[:skip_prompt],
33
+ :force => options[:force]
34
+ }
35
+ Operation::Module.delete_from_remote(operation_args)
30
36
  end
31
37
  end
32
38
  end
@@ -21,10 +21,18 @@ module DTK::Client
21
21
  subcommand_def 'pull-dtkn' do |c|
22
22
  command_body c, 'pull-dtkn', 'Pull content from repo manager to client module directory and push to server' do |sc|
23
23
  sc.flag Token.directory_path, :desc => 'Absolute or relative path to module directory containing content to update; not need if in the module directory'
24
+ sc.switch Token.skip_prompt
24
25
  sc.action do |_global_options, options, _args|
25
26
  module_ref = module_ref_object_from_options_or_context(options)
26
- Operation::Module.pull_dtkn(:module_ref => module_ref, :base_dsl_file_obj => @base_dsl_file_obj)
27
- Operation::Module.push(:module_ref => module_ref, :base_dsl_file_obj => @base_dsl_file_obj, :directory_path => options[:directory_path], :method => "pulled")
27
+ operation_args = {
28
+ :module_ref => module_ref,
29
+ :base_dsl_file_obj => @base_dsl_file_obj,
30
+ :has_directory_param => !options["d"].nil?,
31
+ :directory_path => options[:directory_path],
32
+ :skip_prompt => options[:skip_prompt]
33
+ }
34
+ Operation::Module.pull_dtkn(operation_args)
35
+ Operation::Module.push(operation_args.merge(:method => "pulled"))
28
36
  end
29
37
  end
30
38
  end
data/lib/cli/runner.rb CHANGED
@@ -44,10 +44,31 @@ module DTK::Client
44
44
  end
45
45
 
46
46
  private
47
-
47
+
48
+ CONNECTION_RETRIES = 20
49
+ SLEEP_BETWEEN_RETRIES = 1
48
50
  def self.raise_error_if_invalid_connection
49
- connection = Session.get_connection
50
- raise Error::InvalidConnection.new(connection) if connection.connection_error?
51
+ connection_retries = connection_retries()
52
+ count = 0
53
+ while count < connection_retries
54
+ connection = Session.get_connection(count == 0 ? {} : { reset: true })
55
+ return unless connection.connection_error?
56
+ if connection.connection_refused_error_code?
57
+ sleep SLEEP_BETWEEN_RETRIES
58
+ count += 1
59
+ else
60
+ raise Error::InvalidConnection.new(connection)
61
+ end
62
+ end
63
+ raise Error::InvalidConnection.new(connection)
64
+ end
65
+
66
+ def self.connection_retries
67
+ ret =
68
+ if env_val = ENV['DTK_CONNECTION_RETRIES']
69
+ env_val.to_i rescue nil
70
+ end
71
+ ret || CONNECTION_RETRIES
51
72
  end
52
73
 
53
74
  def self.render_response(response_obj)
data/lib/cli/version.rb CHANGED
@@ -18,7 +18,7 @@
18
18
  module DTK
19
19
  module Client
20
20
  module CLI
21
- VERSION="0.10.4"
21
+ VERSION="0.10.5"
22
22
  end
23
23
  end
24
24
  end
@@ -10,8 +10,6 @@ auto_commit_changes=false # autocommit for modules
10
10
  verbose_rest_calls=false # logging of REST calls
11
11
 
12
12
  service_instance_location=service
13
- module_location=component-modules
14
- service_location=service-modules
15
13
  assembly_module_base_location=assemblies
16
14
  backups_location=backups
17
15
 
data/lib/client/conn.rb CHANGED
@@ -67,10 +67,6 @@ module DTK::Client
67
67
  check_and_wrap_response { json_parse_if_needed(post_raw(url,post_body,{:content_type => 'avro/binary'})) }
68
68
  end
69
69
 
70
- def connection_error?
71
- !@connection_error.nil?
72
- end
73
-
74
70
  ##
75
71
  # Method will warn user that connection could not be established. User should check configuration
76
72
  # to make sure that connection is properly set.
@@ -84,14 +80,25 @@ module DTK::Client
84
80
  printf "%15s %s\n", "Password:", "#{creds[:password] ? creds[:password].gsub(/./,'*') : 'No password set'}"
85
81
  puts "==================================================================="
86
82
 
87
- if connection_error['errors'].first['errors']
88
- error_code = self.connection_error['errors'].first['errors'].first['code']
83
+ if error_code = error_code?
89
84
  OsUtil.print_error("Error code: #{error_code}")
90
85
  end
91
86
  end
87
+
88
+ def connection_error?
89
+ !connection_error.nil?
90
+ end
91
+
92
+ def connection_refused_error_code?
93
+ error_code? == 'connection_refused'
94
+ end
92
95
 
93
96
  private
94
97
 
98
+ def error_code?
99
+ connection_error['errors'].first['code'] rescue nil
100
+ end
101
+
95
102
  REST_VERSION = 'v1'
96
103
  REST_PREFIX = "rest/api/#{REST_VERSION}"
97
104
  # REST_PREFIX = "rest"
@@ -149,7 +156,7 @@ module DTK::Client
149
156
  @cookies = response.cookies
150
157
  end
151
158
  end
152
-
159
+
153
160
  def logout
154
161
  response = get_raw rest_url('auth/logout')
155
162
  # TODO: see if response can be nil
@@ -86,7 +86,7 @@ module DTK::Client
86
86
  @bad_connection = bad_connection
87
87
  end
88
88
  def print_warning
89
- @bad_connection.print_warning
89
+ @bad_connection.print_warning if @bad_connection
90
90
  end
91
91
  end
92
92
 
@@ -26,10 +26,39 @@ module DTK::Client
26
26
  extend ErrorHandler::Mixin
27
27
 
28
28
  attr_accessor :git_repo
29
+
30
+ # Monkey patch the git merge method
31
+ # to allow passing the --allow-unrelated-histories flag
32
+ # more info: http://stackoverflow.com/questions/37937984/git-refusing-to-merge-unrelated-histories
33
+ class ::Git::Base
34
+ def merge(branch, message = 'merge', opts = {})
35
+ self.lib.merge(branch, message, opts)
36
+ end
37
+
38
+ def rev_list(sha)
39
+ self.lib.rev_list(sha)
40
+ end
41
+ end
42
+
43
+ class ::Git::Lib
44
+ def merge(branch, message = nil, opts = {})
45
+ arr_opts = []
46
+ arr_opts << '--allow-unrelated-histories' if opts[:allow_unrelated_histories]
47
+ arr_opts << '-m' << message if message
48
+ arr_opts += [branch]
49
+ command('merge', arr_opts)
50
+ end
51
+
52
+ def rev_list(sha)
53
+ arr_opts = [sha]
54
+ command('rev-list', arr_opts)
55
+ end
56
+ end
29
57
 
30
58
  # opts can have keys
31
59
  # :branch
32
60
  def initialize(repo_dir, opts = {})
61
+ @repo_dir = repo_dir
33
62
  @git_repo = ::Git.init(repo_dir)
34
63
  # If we want to log Git interaction
35
64
  # @git_repo = ::Git.init(repo_dir, :log => Logger.new(STDOUT))
@@ -80,7 +109,7 @@ module DTK::Client
80
109
  end
81
110
 
82
111
  def merge(branch_to_merge_from)
83
- @git_repo.merge(branch_to_merge_from)
112
+ @git_repo.merge(branch_to_merge_from, 'merge', :allow_unrelated_histories => allow_unrelated_histories?)
84
113
  end
85
114
 
86
115
  def status
@@ -121,7 +150,24 @@ module DTK::Client
121
150
  def reset_soft(sha)
122
151
  @git_repo.reset(sha)
123
152
  end
124
-
153
+
154
+ def reset_hard(sha)
155
+ @git_repo.reset_hard(sha)
156
+ end
157
+
158
+ def revparse(sha_or_string)
159
+ @git_repo.revparse(sha_or_string)
160
+ end
161
+
162
+ def rev_list(base_sha)
163
+ @git_repo.rev_list(base_sha)
164
+ end
165
+
166
+ def local_ahead(base_sha, remote_sha)
167
+ results = @git_repo.rev_list(base_sha)
168
+ !results.split("\n").grep(remote_sha).empty?
169
+ end
170
+
125
171
  def stage_changes()
126
172
  handle_git_error do
127
173
  @git_repo.add(untracked())
@@ -150,7 +196,9 @@ module DTK::Client
150
196
  end
151
197
 
152
198
  def add_all
153
- @git_repo.add(:all => true)
199
+ # Cannot use '@git_repo.add(:all => true)' because this only works if pwd is base git repo
200
+ fully_qualified_repo_dir = (@repo_dir =~ /^\// ? @repo_dir : File.join(Dir.pwd, @repo_dir))
201
+ @git_repo.add(fully_qualified_repo_dir, :all => true )
154
202
  end
155
203
 
156
204
  def is_there_remote?(remote_name)
@@ -232,6 +280,13 @@ module DTK::Client
232
280
  "DTK Commit from client"
233
281
  end
234
282
 
283
+ def allow_unrelated_histories?
284
+ git_version_output = `git --version`
285
+ git_version = git_version_output.split.last
286
+ # --allow-unrelated_histories was introduced in git 2.9
287
+ Gem::Version.new(git_version) >= Gem::Version.new('2.9.0')
288
+ end
289
+
235
290
  end
236
291
  end
237
292
  end
@@ -28,9 +28,12 @@ module DTK::Client
28
28
  # opts can have keys
29
29
  # :branch
30
30
  def initialize(repo_dir, opts = {})
31
+ @repo_dir = repo_dir
31
32
  @git_adapter = git_adapter_class.new(repo_dir, opts)
32
33
  end
33
34
 
35
+ attr_reader :repo_dir
36
+
34
37
  def self.clone(repo_url, target_path, branch)
35
38
  git_adapter_class.clone(repo_url, target_path, branch)
36
39
  end
@@ -146,6 +149,26 @@ module DTK::Client
146
149
  @git_adapter.reset_soft(sha)
147
150
  end
148
151
 
152
+ def reset_hard(sha)
153
+ @git_adapter.reset_hard(sha)
154
+ end
155
+
156
+ def revparse(string)
157
+ @git_adapter.revparse(string)
158
+ end
159
+
160
+ def rev_list(base_sha)
161
+ @git_adapter.rev_list(base_sha)
162
+ end
163
+
164
+ def local_ahead(base_sha, remote_sha)
165
+ @git_adapter.local_ahead(base_sha, remote_sha)
166
+ end
167
+
168
+ def add_all
169
+ @git_adapter.add_all
170
+ end
171
+
149
172
  def all_branches
150
173
  @git_adapter.all_branches
151
174
  end
@@ -20,8 +20,10 @@ module DTK::Client
20
20
  class ComponentInfo < self
21
21
  def fetch_and_cache_info
22
22
  fetch_remote
23
- merge_from_remote
24
- transform_from_component_info
23
+ unless local_ahead?.data('local_ahead')
24
+ merge_from_remote
25
+ transform_from_component_info
26
+ end
25
27
  end
26
28
 
27
29
  def fetch_info
@@ -20,8 +20,10 @@ module DTK::Client
20
20
  class ServiceInfo < self
21
21
  def fetch_and_cache_info
22
22
  fetch_remote
23
- merge_from_remote
24
- transform_from_service_info
23
+ unless local_ahead?.data('local_ahead')
24
+ merge_from_remote
25
+ transform_from_service_info
26
+ end
25
27
  end
26
28
 
27
29
  def fetch_info
@@ -111,6 +111,11 @@ module DTK::Client
111
111
  git_repo_operation.merge_from_dtkn_remote(git_repo_args)
112
112
  end
113
113
 
114
+ def local_ahead?
115
+ git_repo_args = common_git_repo_args.merge(:remote_branch => git_repo_remote_branch, :no_commit => true)
116
+ git_repo_operation.local_ahead?(git_repo_args)
117
+ end
118
+
114
119
  def self.stage_and_commit(target_repo_dir, commit_msg = nil)
115
120
  git_repo_args = {
116
121
  :repo_dir => target_repo_dir,
@@ -51,6 +51,11 @@ module DTK::Client
51
51
  Internal.merge(@repo, merge_from_ref, :no_commit => opts[:no_commit])
52
52
  end
53
53
 
54
+ def local_ahead?(remote_branch, opts = {})
55
+ merge_from_ref = "#{remote_name}/#{remote_branch}"
56
+ Internal.local_ahead?(@repo, merge_from_ref, :no_commit => opts[:no_commit])
57
+ end
58
+
54
59
  private
55
60
 
56
61
  # TODO: These constants used in Internal; Deprecate GIT_REMOTE amd LOCAL_BRANCH for remote_name and local_branch
@@ -61,10 +61,11 @@ module DTK::Client
61
61
  repo.head_commit_sha
62
62
  end
63
63
 
64
- def self.checkout_branch__return_repo(repo_dir, local_branch, opts = {})
65
- repo = create_empty_git_repo?(repo_dir, :branch => local_branch)
66
- repo.checkout(local_branch)
67
- repo
64
+ def self.local_ahead?(repo, merge_from_ref, opts = {})
65
+ base_sha = repo.head_commit_sha
66
+ remote_branch = repo.all_branches.remote.find { |r| "#{r.remote}/#{r.name}" == merge_from_ref }
67
+ remote_sha = remote_branch.gcommit.sha
68
+ repo.local_ahead(base_sha, remote_sha)
68
69
  end
69
70
 
70
71
  # opts can have keys:
@@ -251,7 +252,7 @@ module DTK::Client
251
252
  service_instance = args.required(:service_instance)
252
253
  path = args.required(:path)
253
254
  content = args.required(:content)
254
- checkout_branch(service_instance, branch) do
255
+ checkout_branch_on_service_instance(service_instance, branch) do
255
256
  File.open(qualified_path(service_instance, path), 'w') { |f| f.write(content) }
256
257
  end
257
258
  end
@@ -261,7 +262,7 @@ module DTK::Client
261
262
  branch = args.required(:branch)
262
263
  service_instance = args.required(:service_instance)
263
264
  path = args.required(:path)
264
- checkout_branch(service_instance, branch) do
265
+ checkout_branch_on_service_instance(service_instance, branch) do
265
266
  qualified_path = qualified_path(service_instance, path)
266
267
  if File.exists?(qualified_path)
267
268
  File.open(qualified_path, 'r').read
@@ -301,18 +302,29 @@ module DTK::Client
301
302
  "#{repo_dir}/#{relative_path}"
302
303
  end
303
304
 
305
+ def self.checkout_branch_on_service_instance(service_instance, branch, &body)
306
+ repo = git_repo.new(ret_base_path(:service, service_instance), :branch => branch)
307
+ checkout_branch_in_repo(repo, branch, &block)
308
+ end
309
+
304
310
  CHECKOUT_LOCK = Mutex.new
305
- def self.checkout_branch(service_instance, branch, &body)
311
+ # opts can have keys
312
+ # :current_branch
313
+ def self.checkout_branch(repo, branch_to_checkout, opts = {}, &block)
306
314
  ret = nil
307
315
  CHECKOUT_LOCK.synchronize do
308
- repo = git_repo.new(ret_base_path(:service, service_instance), :branch => branch)
309
- current_branch = repo.current_branch.name
310
- if current_branch == branch
311
- ret = yield
316
+ current_branch = opts[:current_branch] || repo.current_branch.name
317
+ if current_branch == branch_to_checkout
318
+ ret = reset_if_error(repo, branch_to_checkout) { yield }
312
319
  else
320
+ #TODO: DTK-2922: temporary fix until can solve problem described in note below
321
+ unless repo.repo_dir == Dir.pwd
322
+ raise Error::Usage, "This command must be invoked from the base module directory '#{repo.repo_dir}'"
323
+ end
324
+
313
325
  begin
314
- repo.checkout(branch)
315
- ret = yield
326
+ repo.checkout(branch_to_checkout)
327
+ ret = reset_if_error(repo, branch_to_checkout) { yield }
316
328
  ensure
317
329
  repo.checkout(current_branch)
318
330
  end
@@ -321,6 +333,31 @@ module DTK::Client
321
333
  ret
322
334
  end
323
335
 
336
+ #TODO: DTK-2922: tried below for above; it worked aside from fact that dircetory is empty and have to step down and step up
337
+ # Dir.chdir is done to avoid case where current directory does not exist in branch checking out
338
+ # Dir.chdir(repo.repo_dir) do
339
+ # begin
340
+ # repo.checkout(branch_to_checkout)
341
+ # ret = reset_if_error(repo, branch_to_checkout) { yield }
342
+ # ensure
343
+ # repo.checkout(current_branch)
344
+ # end
345
+ # end
346
+
347
+ def self.reset_if_error(repo, branch, &block)
348
+ ret = nil
349
+ begin
350
+ sha_before_operations = repo.revparse(branch)
351
+ ret = yield
352
+ rescue => e
353
+ # reset to enable checkout of another branch
354
+ repo.add_all
355
+ repo.reset_hard(sha_before_operations)
356
+ raise e
357
+ end
358
+ ret
359
+ end
360
+
324
361
  end
325
362
  end
326
363
  end
@@ -72,7 +72,29 @@ module DTK::Client
72
72
  end
73
73
  end
74
74
 
75
+ # The retries are put in to avoid race condition when the keys are not yet in repo manager gitolite
76
+ DEFAULT_NUM_DTKN_FETCH_RETRIES = 20
77
+ SLEEP_BETWEEN_RETRIES = 1
75
78
  def self.fetch_dtkn_remote(args)
79
+ if num_retries = ENV['NUM_DTKN_FETCH_RETRIES']
80
+ num_retries = num_retries.to_i rescue nil
81
+ end
82
+ num_retries ||= DEFAULT_NUM_DTKN_FETCH_RETRIES
83
+ ret = nil
84
+ while num_retries > 0
85
+ num_retries -= 1
86
+ begin
87
+ if ret = fetch_dtkn_remote_single_try(args)
88
+ return ret
89
+ end
90
+ rescue => e
91
+ fail e if num_retries == 0
92
+ end
93
+ end
94
+ ret # should not be reached
95
+ end
96
+
97
+ def self.fetch_dtkn_remote_single_try(args)
76
98
  wrap_operation(args) do |args|
77
99
  repo_with_remote = repo_with_dtkn_remote(args)
78
100
 
@@ -80,6 +102,7 @@ module DTK::Client
80
102
  response_data_hash
81
103
  end
82
104
  end
105
+ private_class_method :fetch_dtkn_remote_single_try
83
106
 
84
107
  def self.merge_from_dtkn_remote(args)
85
108
  wrap_operation(args) do |args|
@@ -91,11 +114,34 @@ module DTK::Client
91
114
  end
92
115
  end
93
116
 
94
- def self.checkout_branch__return_repo(args)
117
+ def self.local_ahead?(args)
95
118
  wrap_operation(args) do |args|
96
- repo_dir = args.required(:repo_dir)
97
- local_branch = args.required(:local_branch)
98
- response_data_hash(:repo => Internal.checkout_branch__return_repo(repo_dir, local_branch))
119
+ remote_branch = args.required(:remote_branch)
120
+ no_commit = args[:no_commit]
121
+ repo_with_remote = repo_with_dtkn_remote(args)
122
+
123
+ response_data_hash(:local_ahead => repo_with_remote.local_ahead?(remote_branch, :no_commit => no_commit))
124
+ end
125
+ end
126
+
127
+ def self.create_empty_git_repo?(args)
128
+ wrap_operation(args) do |args|
129
+ repo_dir = args.required(:repo_dir)
130
+ branch = args.required(:branch)
131
+
132
+ response_data_hash(:repo => Internal.create_empty_git_repo?(repo_dir, :branch => branch))
133
+ end
134
+ end
135
+
136
+ # The arg repo wil have a branch. This funbctio checks that out and when finished goes back to current_branch
137
+ def self.checkout_branch(args, &block)
138
+ wrap_operation(args) do |args|
139
+ repo = args.required(:repo)
140
+ current_branch = args.required(:current_branch)
141
+ branch_to_checkout = args.required(:branch_to_checkout)
142
+
143
+ Internal.checkout_branch(repo, branch_to_checkout, :current_branch => current_branch, &block)
144
+ response_data_hash
99
145
  end
100
146
  end
101
147
 
@@ -115,6 +115,7 @@ module DTK::Client
115
115
  end
116
116
 
117
117
  def self.create_file_with_content(file_path, content)
118
+ FileUtils.mkdir_p(File.dirname(file_path))
118
119
  File.open(file_path, 'w') { |f| f << content }
119
120
  end
120
121
 
@@ -123,8 +124,6 @@ module DTK::Client
123
124
  def self.base_path(type)
124
125
  path =
125
126
  case type.to_sym
126
- when :service_module then Config[:service_location]
127
- when :component_module then Config[:module_location]
128
127
  when :service then Config[:instance_location]
129
128
  else raise Error, "Unexpected type (#{type}) when determining base path"
130
129
  end
@@ -29,7 +29,7 @@ module DTK::Client
29
29
  def self.execute(args = Args.new)
30
30
  wrap_operation(args) do |args|
31
31
  module_ref = args.required(:module_ref)
32
- new('dtkn', module_ref).delete_from_remote(:skip_prompt => args[:skip_prompt])
32
+ new('dtkn', module_ref).delete_from_remote(:skip_prompt => args[:skip_prompt], :force => args[:force])
33
33
  end
34
34
  end
35
35
 
@@ -38,6 +38,7 @@ module DTK::Client
38
38
  :module_name => module_ref.module_name,
39
39
  :namespace => module_ref.namespace,
40
40
  :rsa_pub_key => SSHUtil.rsa_pub_key_content,
41
+ :force? => opts[:force]
41
42
  )
42
43
 
43
44
  unless version = module_ref.version
@@ -95,6 +95,14 @@ module DTK::Client; class Operation::Module
95
95
  end
96
96
 
97
97
  dependencies = convert_to_module_refs_array(response)
98
+
99
+ # to avoid cases where dependency can have itself as dependency (stack level too deep) we remove it from dependencies
100
+ # think we will not need this when we have unified module (instead of component and service modules)
101
+ if @module_ref.is_base_module?
102
+ matching = dependencies.find{ |dep| (dep.module_name == module_name) && (dep.namespace == namespace) && (dep.version == version) }
103
+ dependencies.delete(matching)
104
+ end
105
+
98
106
  @cache.add!(@module_ref, dependencies)
99
107
  dependencies
100
108
  end
@@ -45,6 +45,7 @@ module DTK::Client; class Operation::Module
45
45
  end
46
46
 
47
47
  def query_if_component_module_is_installed?
48
+ # TODO: :type => :component_module is for legacy; once we get past having legacy can change to :common_module
48
49
  module_version_exists?(@module_ref, :type => :component_module)
49
50
  end
50
51
 
@@ -59,15 +60,13 @@ module DTK::Client; class Operation::Module
59
60
  :namespace => namespace,
60
61
  :rsa_pub_key => SSHUtil.rsa_pub_key_content,
61
62
  :version? => version,
62
- :full_module_name => full_module_name,
63
- :json_diffs => ""
63
+ :force => true # TODO: hardwired
64
64
  }
65
- response = rest_post "#{BaseRoute}/pull_component_module_from_remote", PostBody.new(post_body)
65
+ response = rest_post "#{BaseRoute}/pull_component_info_from_remote", PostBody.new(post_body)
66
66
 
67
- if custom_message = response.data[:custom_message]
68
- OsUtil.print(custom_message)
69
- elsif (response.data[:diffs].nil? || response.data[:diffs].empty?)
70
- OsUtil.print("No changes to pull from remote.", :yellow) unless response['errors']
67
+ if (response.data(:diffs) || {}).empty?
68
+ # OsUtil.print("No changes to pull from remote.", :yellow) unless response['errors']
69
+ OsUtil.print("No changes to pull from remote.", :yellow)
71
70
  else
72
71
  OsUtil.print("Changes pulled from remote", :green)
73
72
  end
@@ -32,6 +32,7 @@ module DTK::Client
32
32
  @component_module_refs = component_module_refs
33
33
  @print_helper = PrintHelper.new(:module_ref => @base_module_ref, :source => :remote)
34
34
  @prompt_helper = PromptHelper.new(:update_all => opts[:skip_prompt], :update_none => opts[:update_none])
35
+ @opts = opts
35
36
  end
36
37
  private :initialize
37
38
 
@@ -44,7 +45,12 @@ module DTK::Client
44
45
  @print_helper.print_getting_dependencies
45
46
  unified_module_refs = get_unified_dependent_module_refs
46
47
  unless unified_module_refs.empty?
47
- @print_helper.print_installing_dependencies
48
+ case @opts[:mode]
49
+ when 'pull'
50
+ @print_helper.print_pulling_dependencies
51
+ else
52
+ @print_helper.print_installing_dependencies
53
+ end
48
54
  unified_module_refs.each do |module_ref|
49
55
  # Using unless module_ref.is_base_module? because Base component module is installed when base is installed
50
56
  ComponentModule.install_or_pull?(module_ref, @prompt_helper, @print_helper) unless module_ref.is_base_module?
@@ -44,6 +44,10 @@ module DTK::Client; class Operation::Module
44
44
  print_continuation "Installing base module '#{pretty_print_module}' from #{source_term}", :color => :yellow
45
45
  end
46
46
 
47
+ def print_continuation_pulling_base_module
48
+ print_continuation "Pulling base module '#{pretty_print_module}' from #{source_term}", :color => :yellow
49
+ end
50
+
47
51
  def print_continuation_pulling_dependency_update
48
52
  print_continuation "Pulling update to dependent module '#{pretty_print_module}'"
49
53
  end
@@ -62,6 +66,10 @@ module DTK::Client; class Operation::Module
62
66
  OsUtil.print_info("Installing dependent modules from #{Term::DTKN_CATALOG} #{Term::CONTINUATION}")
63
67
  end
64
68
 
69
+ def print_pulling_dependencies
70
+ OsUtil.print_info("Pulling dependent modules from #{Term::DTKN_CATALOG} #{Term::CONTINUATION}")
71
+ end
72
+
65
73
  def print_using_installed_dependent_module
66
74
  OsUtil.print("Using installed dependent module '#{pretty_print_module}'")
67
75
  end
@@ -70,6 +78,10 @@ module DTK::Client; class Operation::Module
70
78
  OsUtil.print_warning("Terminated installation of module '#{pretty_print_module}'")
71
79
  end
72
80
 
81
+ def print_terminated_pulling
82
+ OsUtil.print_warning("Terminated pulling of module '#{pretty_print_module}'")
83
+ end
84
+
73
85
  def print_done_message
74
86
  OsUtil.print('Done.', :yellow)
75
87
  end
@@ -26,20 +26,31 @@ module DTK::Client
26
26
  @target_repo_dir = directory_path || base_dsl_file_obj.parent_dir
27
27
  @version = version # if nil wil be dynamically updated
28
28
  @base_dsl_file_obj = base_dsl_file_obj
29
+ @parsed_module = base_dsl_file_obj.parse_content(:common_module_summary)
30
+ @print_helper = Install::PrintHelper.new(:module_ref => module_ref, :source => :remote)
29
31
  end
30
32
  private :initialize
31
33
 
32
34
  def self.execute(args = Args.new)
33
35
  wrap_operation(args) do |args|
34
- module_ref = args.required(:module_ref)
35
- version = args[:version] || module_ref.version
36
- base_dsl_file_obj = args[:base_dsl_file_obj]
37
- directory_path = args[:directory_path]
38
- new('dtkn', module_ref, directory_path, version, base_dsl_file_obj).pull_dtkn
36
+ module_ref = args.required(:module_ref)
37
+ base_dsl_file_obj = args.required(:base_dsl_file_obj)
38
+ version = args[:version] || module_ref.version
39
+ directory_path = args[:directory_path]
40
+ has_directory_param = args[:has_directory_param]
41
+ skip_prompt = args[:skip_prompt]
42
+
43
+ if has_directory_param
44
+ file_obj = base_dsl_file_obj.raise_error_if_no_content_flag(:module_ref)
45
+ else
46
+ file_obj = base_dsl_file_obj.raise_error_if_no_content
47
+ end
48
+
49
+ new('dtkn', module_ref, directory_path, version, file_obj).pull_dtkn(:skip_prompt => skip_prompt)
39
50
  end
40
51
  end
41
52
 
42
- def pull_dtkn
53
+ def pull_dtkn(opts = {})
43
54
  # TODO: DTK-2765: not sure if we need module to exist on server to do push-dtkn
44
55
  unless module_version_exists?(@module_ref, :type => :common_module)
45
56
  raise Error::Usage, "Module #{@module_ref.print_form} does not exist on server"
@@ -65,10 +76,48 @@ module DTK::Client
65
76
  @module_ref.version = @version
66
77
  end
67
78
 
79
+ unless dependent_modules.empty?
80
+ begin
81
+ Install::DependentModules.install(@module_ref, dependent_modules, :skip_prompt => opts[:skip_prompt], :mode => 'pull')
82
+ # Install::DependentModules.install(@module_ref, dependent_modules, :skip_prompt => false, :mode => 'pull')
83
+ rescue Install::TerminateInstall
84
+ @print_helper.print_terminated_pulling
85
+ return nil
86
+ end
87
+ end
88
+
89
+ @print_helper.print_continuation_pulling_base_module
68
90
  LoadSource.fetch_transform_and_merge(remote_module_info, self, :stage_and_commit_steps => true)
91
+
69
92
  nil
70
93
  end
71
94
 
95
+ private
96
+
97
+ def dependent_modules
98
+ @dependent_modules ||= compute_dependent_modules
99
+ end
100
+
101
+ def compute_dependent_modules
102
+ base_component_module_found = false
103
+ ret = (@parsed_module.val(:DependentModules) || []).map do |parsed_module_ref|
104
+ dep_module_name = parsed_module_ref.req(:ModuleName)
105
+ dep_namespace = parsed_module_ref.req(:Namespace)
106
+ dep_version = parsed_module_ref.val(:ModuleVersion)
107
+ if is_base_module = (dep_module_name == @module_ref.module_name)
108
+ # This is for legacy modules
109
+ base_component_module_found = true
110
+ end
111
+ Install::ModuleRef.new(:namespace => dep_namespace, :module_name => dep_module_name, :version => dep_version, :is_base_module => is_base_module)
112
+ end
113
+ unless base_component_module_found
114
+ if module_version_exists?(@module_ref, :type => :component_module)
115
+ ret << Install::ModuleRef.new(:namespace => @module_ref.namespace, :module_name => @module_ref.module_name, :version => @module_ref.version, :is_base_module => true)
116
+ end
117
+ end
118
+ ret
119
+ end
120
+
72
121
  end
73
122
  end
74
123
  end
@@ -66,8 +66,6 @@ module DTK::Client
66
66
  end
67
67
  response = rest_post("#{BaseRoute}/update_from_repo", post_body.merge(:skip_missing_check => true))
68
68
  end
69
- # TODO: DTK-2786; uncomment out to see what diffs is returning for different examples of what is deleted, added or modified before push
70
- # pp [:debug_diffs, response.data(:diffs)]
71
69
  print = process_semantic_diffs(response.data(:diffs), method)
72
70
 
73
71
  # if diffs is nil then indicate no diffs, otherwise render diffs in yaml
@@ -22,6 +22,7 @@ module DTK::Client
22
22
  # attr_reader :parsed_common_module
23
23
 
24
24
  def transform_info
25
+ fetch_remote
25
26
  transform_to_component_info
26
27
  end
27
28
 
@@ -20,6 +20,7 @@ module DTK::Client
20
20
  class ConvertSource
21
21
  class ServiceInfo < self
22
22
  def transform_info
23
+ fetch_remote
23
24
  transform_to_service_info
24
25
  end
25
26
 
@@ -33,14 +33,14 @@ module DTK::Client; class Operation::Module
33
33
  def self.transform_and_commit(remote_module_info, parent)
34
34
  target_repo_dir = parent.target_repo_dir
35
35
  parsed_common_module = parent.base_dsl_file_obj.parse_content(:common_module)
36
- local_branch = Operation::ClientModuleDir::GitRepo.current_branch(:path => target_repo_dir).data(:branch)
36
+ current_branch = Operation::ClientModuleDir::GitRepo.current_branch(:path => target_repo_dir).data(:branch)
37
37
 
38
38
  if service_info = remote_module_info.data(:service_info)
39
- transform_service_info(target_repo_dir, parent, service_info, parsed_common_module, local_branch)
39
+ transform_service_info(target_repo_dir, parent, service_info, parsed_common_module, current_branch)
40
40
  end
41
41
 
42
42
  if component_info = remote_module_info.data(:component_info)
43
- transform_component_info(target_repo_dir, parent, component_info, parsed_common_module, local_branch)
43
+ transform_component_info(target_repo_dir, parent, component_info, parsed_common_module, current_branch)
44
44
  end
45
45
  end
46
46
 
@@ -48,27 +48,29 @@ module DTK::Client; class Operation::Module
48
48
  new(transform_helper, info_type, remote_repo_url, parent).transform_info
49
49
  end
50
50
 
51
- def self.transform_service_info(target_repo_dir, parent, service_info, parsed_common_module, local_branch = 'master')
51
+ def self.transform_service_info(target_repo_dir, parent, service_info, parsed_common_module, current_branch)
52
52
  transform_helper = ServiceAndComponentInfo::TransformTo.new(target_repo_dir, parent.module_ref, parent.version, parsed_common_module)
53
53
  service_file_path__content_array = ServiceInfo.transform_info(transform_helper, service_info['remote_repo_url'], parent)
54
54
 
55
- repo = checkout_branch__return_repo(target_repo_dir, "remotes/dtkn/master").data(:repo)
56
- FileUtils.mkdir_p("#{target_repo_dir}/assemblies") unless File.exists?("#{target_repo_dir}/assemblies")
57
-
58
- args = [transform_helper, ServiceInfo.info_type, service_info['remote_repo_url'], parent]
59
- service_file_path__content_array.each { |file| Operation::ClientModuleDir.create_file_with_content("#{service_file_path(target_repo_dir, file, *args)}", file[:content]) }
60
-
61
- commit_and_push_to_remote(repo, target_repo_dir, "master", "dtkn", local_branch)
55
+ create_and_checkout_branch?(current_branch, target_repo_dir, "remotes/dtkn/master") do |repo|
56
+ FileUtils.mkdir_p("#{target_repo_dir}/assemblies") unless File.exists?("#{target_repo_dir}/assemblies")
57
+
58
+ args = [transform_helper, ServiceInfo.info_type, service_info['remote_repo_url'], parent]
59
+ service_file_path__content_array.each { |file| Operation::ClientModuleDir.create_file_with_content("#{service_file_path(target_repo_dir, file, *args)}", file[:content]) }
60
+
61
+ commit_and_push_to_remote(repo, target_repo_dir, "master", "dtkn")
62
+ end
62
63
  end
63
64
 
64
- def self.transform_component_info(target_repo_dir, parent, component_info, parsed_common_module, local_branch = 'master')
65
+ def self.transform_component_info(target_repo_dir, parent, component_info, parsed_common_module, current_branch)
65
66
  transform_helper = ServiceAndComponentInfo::TransformTo.new(target_repo_dir, parent.module_ref, parent.version, parsed_common_module)
66
67
  component_file_path__content_array = ComponentInfo.transform_info(transform_helper, component_info['remote_repo_url'], parent)
67
68
 
68
- repo = checkout_branch__return_repo(target_repo_dir, "remotes/dtkn-component-info/master").data(:repo)
69
- component_file_path__content_array.each { |file| Operation::ClientModuleDir.create_file_with_content("#{file_path(target_repo_dir, file)}", file[:content]) }
69
+ create_and_checkout_branch?(current_branch, target_repo_dir, "remotes/dtkn-component-info/master") do |repo|
70
+ component_file_path__content_array.each { |file| Operation::ClientModuleDir.create_file_with_content("#{file_path(target_repo_dir, file)}", file[:content]) }
70
71
 
71
- commit_and_push_to_remote(repo, target_repo_dir, "master", "dtkn-component-info", local_branch)
72
+ commit_and_push_to_remote(repo, target_repo_dir, "master", "dtkn-component-info")
73
+ end
72
74
  end
73
75
 
74
76
  private
@@ -103,18 +105,33 @@ module DTK::Client; class Operation::Module
103
105
  "#{target_repo_dir}/assemblies/#{assembly_name}/assembly.yaml"
104
106
  end
105
107
 
106
- def self.checkout_branch__return_repo(target_repo_dir, branch)
107
- git_repo_args = {
108
- :repo_dir => target_repo_dir,
109
- :local_branch => branch
108
+ def fetch_remote
109
+ git_repo_args = common_git_repo_args.merge(:add_remote => @remote_repo_url)
110
+ git_repo_operation.fetch_dtkn_remote(git_repo_args)
111
+ end
112
+
113
+ def common_git_repo_args
114
+ {
115
+ :info_type => @info_type,
116
+ :repo_dir => @target_repo_dir
117
+ }
118
+ end
119
+
120
+ def self.create_and_checkout_branch?(current_branch, target_repo_dir, branch_to_checkout, &body)
121
+ repo = git_repo_operation.create_empty_git_repo?(:repo_dir => target_repo_dir, :branch => branch_to_checkout).data(:repo)
122
+
123
+ checkout_branch_args = {
124
+ :repo => repo,
125
+ :current_branch => current_branch,
126
+ :branch_to_checkout => branch_to_checkout
110
127
  }
111
- git_repo_operation.checkout_branch__return_repo(git_repo_args)
128
+
129
+ git_repo_operation.checkout_branch(checkout_branch_args) { body.call(repo) }
112
130
  end
113
131
 
114
- def self.commit_and_push_to_remote(repo, target_repo_dir, branch, remote, local_branch)
132
+ def self.commit_and_push_to_remote(repo, target_repo_dir, branch, remote)
115
133
  repo.stage_and_commit("Add auto-generated files from push-dtkn")
116
134
  repo.push_from_cached_branch(remote, branch, { :force => true })
117
- repo.checkout(local_branch)
118
135
  end
119
136
 
120
137
  def self.stage_and_commit(target_repo_dir, commit_msg = nil)
@@ -56,7 +56,7 @@ module DTK::Client
56
56
  response = rest_get("#{BaseRoute}/#{service_instance}/info")
57
57
 
58
58
  unless node_info = response.data(:nodes).find{ |node| node_name == node['display_name'] }
59
- raise Error::Usage, "Cannot find info about node with id '#{node_id}'"
59
+ raise Error::Usage, "The node '#{node_name}' does not exist"
60
60
  end
61
61
 
62
62
  data = {}
@@ -31,7 +31,10 @@ module DTK::Client
31
31
  @conn = Conn.new
32
32
  end
33
33
 
34
- def self.get_connection
34
+ # opts can have keys
35
+ # :reset
36
+ def self.get_connection(opts = {})
37
+ instance.conn = Conn.new if opts[:reset]
35
38
  instance.conn
36
39
  end
37
40
 
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.10.4
4
+ version: 0.10.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reactor8
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-06 00:00:00.000000000 Z
11
+ date: 2017-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dtk-common-core
@@ -380,7 +380,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
380
380
  version: '0'
381
381
  requirements: []
382
382
  rubyforge_project:
383
- rubygems_version: 2.5.1
383
+ rubygems_version: 2.4.1
384
384
  signing_key:
385
385
  specification_version: 4
386
386
  summary: DTK CLI client for DTK server interaction.