dtk-client 0.10.4 → 0.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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.