dtk-client 0.5.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +5 -0
  3. data/Gemfile_dev +12 -0
  4. data/README.md +78 -0
  5. data/bin/dtk +54 -0
  6. data/bin/dtk-shell +15 -0
  7. data/dtk-client.gemspec +49 -0
  8. data/lib/auxiliary.rb +13 -0
  9. data/lib/bundler_monkey_patch.rb +9 -0
  10. data/lib/client.rb +48 -0
  11. data/lib/command_helper.rb +16 -0
  12. data/lib/command_helpers/git_repo.rb +391 -0
  13. data/lib/command_helpers/jenkins_client/config_xml.rb +271 -0
  14. data/lib/command_helpers/jenkins_client.rb +91 -0
  15. data/lib/command_helpers/service_importer.rb +99 -0
  16. data/lib/command_helpers/service_link.rb +18 -0
  17. data/lib/command_helpers/ssh_processing.rb +43 -0
  18. data/lib/commands/common/thor/assembly_workspace.rb +1089 -0
  19. data/lib/commands/common/thor/clone.rb +39 -0
  20. data/lib/commands/common/thor/common.rb +34 -0
  21. data/lib/commands/common/thor/edit.rb +168 -0
  22. data/lib/commands/common/thor/list_diffs.rb +84 -0
  23. data/lib/commands/common/thor/pull_clone_changes.rb +11 -0
  24. data/lib/commands/common/thor/pull_from_remote.rb +99 -0
  25. data/lib/commands/common/thor/purge_clone.rb +26 -0
  26. data/lib/commands/common/thor/push_clone_changes.rb +45 -0
  27. data/lib/commands/common/thor/push_to_remote.rb +45 -0
  28. data/lib/commands/common/thor/reparse.rb +36 -0
  29. data/lib/commands/common/thor/set_required_params.rb +29 -0
  30. data/lib/commands/common/thor/task_status.rb +81 -0
  31. data/lib/commands/thor/account.rb +213 -0
  32. data/lib/commands/thor/assembly.rb +329 -0
  33. data/lib/commands/thor/attribute.rb +62 -0
  34. data/lib/commands/thor/component.rb +52 -0
  35. data/lib/commands/thor/component_module.rb +829 -0
  36. data/lib/commands/thor/component_template.rb +153 -0
  37. data/lib/commands/thor/dependency.rb +18 -0
  38. data/lib/commands/thor/developer.rb +105 -0
  39. data/lib/commands/thor/dtk.rb +117 -0
  40. data/lib/commands/thor/library.rb +107 -0
  41. data/lib/commands/thor/node.rb +411 -0
  42. data/lib/commands/thor/node_group.rb +211 -0
  43. data/lib/commands/thor/node_template.rb +88 -0
  44. data/lib/commands/thor/project.rb +17 -0
  45. data/lib/commands/thor/provider.rb +155 -0
  46. data/lib/commands/thor/repo.rb +35 -0
  47. data/lib/commands/thor/service.rb +656 -0
  48. data/lib/commands/thor/service_module.rb +806 -0
  49. data/lib/commands/thor/state_change.rb +10 -0
  50. data/lib/commands/thor/target.rb +94 -0
  51. data/lib/commands/thor/task.rb +100 -0
  52. data/lib/commands/thor/utils.rb +4 -0
  53. data/lib/commands/thor/workspace.rb +437 -0
  54. data/lib/commands.rb +40 -0
  55. data/lib/config/cacert.pem +3785 -0
  56. data/lib/config/client.conf.header +18 -0
  57. data/lib/config/configuration.rb +82 -0
  58. data/lib/config/default.conf +14 -0
  59. data/lib/config/disk_cacher.rb +60 -0
  60. data/lib/configurator.rb +92 -0
  61. data/lib/context_router.rb +23 -0
  62. data/lib/core.rb +460 -0
  63. data/lib/domain/git_adapter.rb +221 -0
  64. data/lib/domain/response.rb +234 -0
  65. data/lib/dtk-client/version.rb +3 -0
  66. data/lib/dtk_constants.rb +23 -0
  67. data/lib/dtk_logger.rb +96 -0
  68. data/lib/error.rb +74 -0
  69. data/lib/git-logs/git.log +0 -0
  70. data/lib/parser/adapters/option_parser.rb +53 -0
  71. data/lib/parser/adapters/thor/common_option_defs.rb +12 -0
  72. data/lib/parser/adapters/thor.rb +509 -0
  73. data/lib/require_first.rb +87 -0
  74. data/lib/search_hash.rb +27 -0
  75. data/lib/shell/context.rb +975 -0
  76. data/lib/shell/context_aux.rb +29 -0
  77. data/lib/shell/domain.rb +447 -0
  78. data/lib/shell/header_shell.rb +27 -0
  79. data/lib/shell/help_monkey_patch.rb +221 -0
  80. data/lib/shell/interactive_wizard.rb +233 -0
  81. data/lib/shell/parse_monkey_patch.rb +22 -0
  82. data/lib/shell/status_monitor.rb +105 -0
  83. data/lib/shell.rb +219 -0
  84. data/lib/util/console.rb +143 -0
  85. data/lib/util/dtk_puppet.rb +46 -0
  86. data/lib/util/os_util.rb +265 -0
  87. data/lib/view_processor/augmented_simple_list.rb +27 -0
  88. data/lib/view_processor/hash_pretty_print.rb +106 -0
  89. data/lib/view_processor/simple_list.rb +139 -0
  90. data/lib/view_processor/table_print.rb +277 -0
  91. data/lib/view_processor.rb +112 -0
  92. data/puppet/manifests/init.pp +72 -0
  93. data/puppet/manifests/params.pp +16 -0
  94. data/puppet/r8meta.puppet.yml +18 -0
  95. data/puppet/templates/bash_profile.erb +2 -0
  96. data/puppet/templates/client.conf.erb +1 -0
  97. data/puppet/templates/dtkclient.erb +2 -0
  98. data/spec/assembly_spec.rb +50 -0
  99. data/spec/assembly_template_spec.rb +51 -0
  100. data/spec/component_template_spec.rb +40 -0
  101. data/spec/dependency_spec.rb +6 -0
  102. data/spec/dtk_shell_spec.rb +13 -0
  103. data/spec/dtk_spec.rb +33 -0
  104. data/spec/lib/spec_helper.rb +10 -0
  105. data/spec/lib/spec_thor.rb +105 -0
  106. data/spec/module_spec.rb +35 -0
  107. data/spec/node_spec.rb +43 -0
  108. data/spec/node_template_spec.rb +25 -0
  109. data/spec/project_spec.rb +6 -0
  110. data/spec/repo_spec.rb +7 -0
  111. data/spec/response_spec.rb +52 -0
  112. data/spec/service_spec.rb +41 -0
  113. data/spec/state_change_spec.rb +7 -0
  114. data/spec/table_print_spec.rb +48 -0
  115. data/spec/target_spec.rb +57 -0
  116. data/spec/task_spec.rb +28 -0
  117. data/views/assembly/augmented_simple_list.rb +12 -0
  118. data/views/assembly_template/augmented_simple_list.rb +12 -0
  119. data/views/list_task/augmented_simple_list.rb +12 -0
  120. metadata +351 -0
@@ -0,0 +1,81 @@
1
+ module DTK::Client
2
+ module TaskStatusMixin
3
+ def task_status_aux(id,type,wait_flag)
4
+ id_field = "#{type}_id".to_sym
5
+ if wait_flag
6
+ # there will be infinite loop until intereputed with CTRL+C
7
+ begin
8
+ response = nil
9
+ loop do
10
+ post_body = {
11
+ id_field => id,
12
+ :format => :table
13
+ }
14
+ response = post rest_url("#{type}/task_status"), post_body
15
+
16
+ raise DTK::Client::DtkError, "[ERROR] #{response['errors'].first['message']}." if response["status"].eql?('notok')
17
+
18
+ # stop pulling when top level task succeds, fails or timeout
19
+ if response and response.data and response.data.first
20
+ #TODO: may fix in server, but now top can have non executing state but a concurrent branch can execute; so
21
+ #chanding bloew for time being
22
+ #break unless response.data.first["status"].eql? "executing"
23
+ # TODO: There is bug where we do not see executing status on start so we have to wait until at
24
+ # least one 'successed' has been found
25
+ is_pending = (response.data.select {|r|r["status"].nil? }).size > 0
26
+ is_executing = (response.data.select {|r|r["status"].eql? "executing"}).size > 0
27
+ is_failed = (response.data.select {|r|r["status"].eql? "failed"}).size > 0
28
+ is_cancelled = response.data.first["status"].eql?("cancelled")
29
+
30
+ # when some of the converge tasks fail, stop task-status --wait and set task status to '' for remaining tasks which are not executed
31
+ if is_failed
32
+ response.data.each {|r| (r["status"] = "") if r["status"].eql?("executing")}
33
+ is_cancelled = true
34
+ end
35
+
36
+ unless (is_executing || is_pending) && !is_cancelled
37
+ system('clear')
38
+ response.print_error_table = true
39
+ response.render_table(:task_status)
40
+ return response
41
+ end
42
+ end
43
+
44
+ response.render_table(:task_status)
45
+ system('clear')
46
+ response.render_data(true)
47
+
48
+ Console.wait_animation("Watching '#{type}' task status [ #{DEBUG_SLEEP_TIME} seconds refresh ] ",DEBUG_SLEEP_TIME)
49
+ end
50
+ rescue Interrupt => e
51
+ puts ""
52
+ # this tells rest of the flow to skip rendering of this response
53
+ response.skip_render = true unless response.nil?
54
+ end
55
+ else
56
+ post_body = {
57
+ id_field => id,
58
+ :format => :table
59
+ }
60
+ response = post rest_url("#{type}/task_status"), post_body
61
+ response.print_error_table = true
62
+ response.render_table(:task_status)
63
+ end
64
+ end
65
+
66
+ def list_task_info_aux(type, id)
67
+ id_sym = "#{type}_id".to_sym
68
+ post_body = {
69
+ id_sym => id,
70
+ :format => :list
71
+ }
72
+ response = post rest_url("#{type}/task_status"), post_body
73
+
74
+ raise DTK::Client::DtkError, "[SERVER ERROR] #{response['errors'].first['message']}." if response["status"].eql?('notok')
75
+
76
+ response.override_command_class("list_task")
77
+ puts response.render_data
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1,213 @@
1
+ dtk_require_from_base('command_helpers/ssh_processing')
2
+ dtk_require_from_base("dtk_logger")
3
+ dtk_require_from_base("util/os_util")
4
+ dtk_require_from_base('configurator')
5
+
6
+ module DTK::Client
7
+ class Account < CommandBaseThor
8
+ include ParseFile
9
+
10
+ KEY_EXISTS_ALREADY_CONTENT = 'key exists already'
11
+
12
+ no_tasks do
13
+ def password_prompt(message, add_options=true)
14
+ begin
15
+ while line = Readline.readline("#{message}: ", add_hist = false)
16
+ raise Interrupt if line.empty?
17
+ return line
18
+ end
19
+ rescue Interrupt => e
20
+ retry
21
+ ensure
22
+ puts "\n" if line.nil?
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.internal_add_user_access(url, post_body, component_name)
28
+ response = post(rest_url(url),post_body)
29
+ key_exists_already = (response.error_message||'').include?(KEY_EXISTS_ALREADY_CONTENT)
30
+ puts "Key exists already for #{component_name}" if key_exists_already
31
+ [response, key_exists_already]
32
+ end
33
+
34
+ def self.add_key(path_to_key, name=nil)
35
+ match, matched_username = nil, nil
36
+
37
+ unless File.file?(path_to_key)
38
+ OsUtil.put_warning "[ERROR] " ,"No ssh key file found at (#{path_to_key}). Path is wrong or it is necessary to generate the public rsa key (e.g., run `ssh-keygen -t rsa`)", :red
39
+ abort
40
+ end
41
+
42
+ rsa_pub_key = File.open(path_to_key){|f|f.read}
43
+
44
+ post_body = { :rsa_pub_key => rsa_pub_key.chomp }
45
+
46
+ post_body.merge!(:username => name.chomp) if name
47
+ proper_response = nil
48
+ response, key_exists_already = Account.internal_add_user_access("service_module/add_user_direct_access", post_body, 'service module')
49
+ return response unless (response.ok? || key_exists_already)
50
+
51
+
52
+ if response.ok?
53
+ proper_response = response
54
+ match = response.data['match']
55
+ matched_username = response.data['matched_username']
56
+ end
57
+
58
+ response, key_exists_already = Account.internal_add_user_access("component_module/add_user_direct_access", post_body, 'component module')
59
+ return response unless (response.ok? || key_exists_already)
60
+ proper_response = response if response.ok?
61
+
62
+ # if either of request passed we will add to known hosts
63
+ if match
64
+ OsUtil.print("Provided RSA public key already exists, user creation aborted!", :yellow)
65
+ elsif proper_response
66
+ repo_manager_fingerprint,repo_manager_dns = proper_response.data_ret_and_remove!(:repo_manager_fingerprint,:repo_manager_dns)
67
+ SshProcessing.update_ssh_known_hosts(repo_manager_dns,repo_manager_fingerprint)
68
+ OsUtil.print("Ssh key added successfully!", :yellow)
69
+
70
+ return proper_response
71
+ else
72
+ nil
73
+ end
74
+ end
75
+
76
+ desc "set-password", "Change password for your dtk user account"
77
+ def set_password(context_params)
78
+ old_pass_prompt, old_pass, new_pass_prompt, confirm_pass_prompt = nil
79
+ cred_file = ::DTK::Client::Configurator.CRED_FILE
80
+ old_pass = parse_key_value_file(cred_file)[:password]
81
+ username = parse_key_value_file(cred_file)[:username]
82
+
83
+ if old_pass.nil?
84
+ OsUtil.print("Unable to retrieve your current password!", :yellow)
85
+ return
86
+ end
87
+
88
+ 3.times do
89
+ old_pass_prompt = password_prompt("Enter old password")
90
+
91
+ break if (old_pass.eql?(old_pass_prompt) || old_pass_prompt.nil?)
92
+ OsUtil.print("Incorrect old password!", :yellow)
93
+ end
94
+ return unless old_pass.eql?(old_pass_prompt)
95
+
96
+ new_pass_prompt = password_prompt("Enter new password")
97
+ return if new_pass_prompt.nil?
98
+ confirm_pass_prompt = password_prompt("Confirm new password")
99
+
100
+ if new_pass_prompt.eql?(confirm_pass_prompt)
101
+ post_body = {:new_password => new_pass_prompt}
102
+ response = post rest_url("account/set_password"), post_body
103
+ return response unless response.ok?
104
+
105
+ ::DTK::Client::Configurator.regenerate_conf_file(cred_file, [['username', "#{username.to_s}"], ['password', "#{new_pass_prompt.to_s}"]], '')
106
+ OsUtil.print("Password changed successfully!", :yellow)
107
+ else
108
+ OsUtil.print("Entered passwords don't match!", :yellow)
109
+ return
110
+ end
111
+ end
112
+
113
+ desc "list-ssh-keys", "Show list of keys that your account profile has saved"
114
+ def list_ssh_keys(context_params)
115
+ username = parse_key_value_file(::DTK::Client::Configurator.CRED_FILE)[:username]
116
+ post_body = {:username => username}
117
+
118
+ response = post rest_url("account/list_ssh_keys"), post_body
119
+ response.render_table(:account_ssh_keys)
120
+ end
121
+
122
+ desc "add-ssh-key NAME [PATH-TO-RSA-PUB-KEY]","Adds direct access to modules. Optional parameters is path to a ssh rsa public key and default is <user-home-dir>/.ssh/id_rsa.pub"
123
+ def add_ssh_key(context_params)
124
+ name, path_to_key = context_params.retrieve_arguments([:option_1!, :option_2],method_argument_names)
125
+ path_to_key ||= SshProcessing.default_rsa_pub_key_path()
126
+ access_granted = Account.add_key(path_to_key, name)
127
+
128
+ FileUtils.touch(DTK::Client::Configurator::DIRECT_ACCESS) if access_granted
129
+ end
130
+
131
+ desc "remove-ssh-key NAME ","Removes user and direct access to modules."
132
+ def remove_ssh_key(context_params)
133
+ name = context_params.retrieve_arguments([:option_1!],method_argument_names)
134
+ post_body = {:username => name.chomp}
135
+
136
+ response = post rest_url("component_module/remove_user_direct_access"), post_body
137
+ return response unless response.ok?
138
+
139
+ response = post rest_url("service_module/remove_user_direct_access"), post_body
140
+ return response unless response.ok?
141
+
142
+ OsUtil.print("Ssh key removed successfully!", :yellow)
143
+ end
144
+
145
+
146
+
147
+ # Will leave this commented for now until we check if above commands work as expected
148
+ #
149
+ # def self.add_access(path_to_key)
150
+ # unless File.file?(path_to_key)
151
+ # raise DTK::Client::DtkError,"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)"
152
+ # end
153
+ # rsa_pub_key = File.open(path_to_key){|f|f.read}
154
+ # post_body = {
155
+ # :rsa_pub_key => rsa_pub_key.chomp
156
+ # }
157
+
158
+ # proper_response = nil
159
+
160
+ # response, key_exists_already = Account.internal_add_user_access("service_module/add_user_direct_access", post_body, 'service module')
161
+ # return response unless (response.ok? || key_exists_already)
162
+ # proper_response = response if response.ok?
163
+
164
+ # response, key_exists_already = Account.internal_add_user_access("component_module/add_user_direct_access", post_body, 'component module')
165
+ # return response unless (response.ok? || key_exists_already)
166
+ # proper_response = response if response.ok?
167
+
168
+ # # if either of request passed we will add to known hosts
169
+ # if proper_response
170
+ # repo_manager_fingerprint,repo_manager_dns = proper_response.data_ret_and_remove!(:repo_manager_fingerprint,:repo_manager_dns)
171
+ # SshProcessing.update_ssh_known_hosts(repo_manager_dns,repo_manager_fingerprint)
172
+ # return proper_response
173
+ # else
174
+ # nil
175
+ # end
176
+ # end
177
+
178
+ # desc "add-direct-access [PATH-TO-RSA-PUB-KEY]","Adds direct access to modules. Optional parameters is path to a ssh rsa public key and default is <user-home-dir>/.ssh/id_rsa.pub"
179
+ # def add_direct_access(context_params)
180
+ # return
181
+ # path_to_key = context_params.retrieve_arguments([:option_1],method_argument_names)
182
+ # path_to_key ||= SshProcessing.default_rsa_pub_key_path()
183
+ # access_granted = Account.add_access(path_to_key)
184
+
185
+ # FileUtils.touch(DTK::Client::Configurator::DIRECT_ACCESS) if access_granted
186
+ # access_granted
187
+ # end
188
+
189
+ # desc "remove-direct-access [PATH-TO-RSA-PUB-KEY]","Removes direct access to modules. Optional paramaeters is path to a ssh rsa public key and default is <user-home-dir>/.ssh/id_rsa.pub"
190
+ # def remove_direct_access(context_params)
191
+ # path_to_key = context_params.retrieve_arguments([:option_1],method_argument_names)
192
+ # path_to_key ||= SshProcessing.default_rsa_pub_key_path()
193
+
194
+ # # path_to_key ||= "#{ENV['HOME']}/.ssh/id_rsa.pub" #TODO: very brittle
195
+ # unless File.file?(path_to_key)
196
+ # raise DTK::Client::DtkError,"No 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)"
197
+ # end
198
+ # rsa_pub_key = File.open(path_to_key){|f|f.read}
199
+ # post_body = {
200
+ # :rsa_pub_key => rsa_pub_key.chomp
201
+ # }
202
+ # response = post rest_url("component_module/remove_user_direct_access"), post_body
203
+ # return response unless response.ok?
204
+
205
+ # response = post rest_url("service_module/remove_user_direct_access"), post_body
206
+ # return response unless response.ok?
207
+
208
+ # FileUtils.rm(DTK::Client::Configurator::DIRECT_ACCESS) if File.exists?(DTK::Client::Configurator::DIRECT_ACCESS)
209
+ # return response
210
+ # end
211
+
212
+ end
213
+ end
@@ -0,0 +1,329 @@
1
+ dtk_require("../../shell/status_monitor")
2
+
3
+ module DTK::Client
4
+ class Assembly < CommandBaseThor
5
+ no_tasks do
6
+ def get_assembly_name(assembly_id)
7
+ name = nil
8
+ 3.times do
9
+ name = get_name_from_id_helper(assembly_id)
10
+ break if name
11
+ end
12
+
13
+ name
14
+ end
15
+
16
+ def get_assembly_stage_name(assembly_list,assembly_template_name)
17
+ name = nil
18
+ current_list = assembly_list.select{|e| e.include?(assembly_template_name)}
19
+
20
+ if current_list.empty?
21
+ name = assembly_template_name
22
+ else
23
+ numbers = []
24
+ base_name = nil
25
+
26
+ assembly_list.each do |assembly|
27
+ match = assembly.match(/#{assembly_template_name}(-)(\d*)/)
28
+ base_name = assembly_template_name if assembly_template_name.include?(assembly)
29
+ numbers << match[2].to_i if match
30
+ end
31
+
32
+ unless base_name
33
+ name = assembly_template_name
34
+ else
35
+ highest = numbers.max||1
36
+ new_highest = highest+1
37
+
38
+ all = (2..new_highest).to_a
39
+ nums = all - numbers
40
+ name = assembly_template_name + "-#{nums.first}"
41
+ end
42
+ end
43
+
44
+ name
45
+ end
46
+ end
47
+
48
+ def self.whoami()
49
+ return :assembly, "assembly/list", {:subtype => 'template'}
50
+ end
51
+
52
+ def self.get_assembly_template_id_for_service(assembly_template_name, service)
53
+ assembly_template_id = nil
54
+ # TODO: See with Rich if there is better way to resolve this
55
+ response = DTK::Client::CommandBaseThor.get_cached_response(:assembly, "assembly/list", {:subtype => 'template' })
56
+ # response = DTK::Client::CommandBaseThor.get_cached_response(:module, "service_module/list")
57
+
58
+ if response.ok?
59
+ unless response['data'].nil?
60
+ response['data'].each do |module_item|
61
+ if ("#{service.to_s}::#{assembly_template_name.to_s}" == (module_item['display_name']))
62
+ assembly_template_id = module_item['id']
63
+ break
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ raise DTK::Client::DtkError, "Illegal name (#{assembly_template_name}) for assembly." if assembly_template_id.nil?
70
+
71
+ return assembly_template_id
72
+ end
73
+
74
+ def self.get_assembly_template_name_for_service(assembly_template_id, service)
75
+ assembly_template_name = nil
76
+ # TODO: See with Rich if there is better way to resolve this
77
+ response = DTK::Client::CommandBaseThor.get_cached_response(:assembly, "assembly/list", {:subtype => 'template' })
78
+
79
+ if response.ok?
80
+ unless response['data'].nil?
81
+ response['data'].each do |module_item|
82
+ if assembly_template_id.to_i == module_item['id']
83
+ assembly_template_name = module_item['display_name'].gsub("#{service.to_s}::",'')
84
+ break
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ raise DTK::Client::DtkError, "Illegal name (#{assembly_template_name}) for assembly." if assembly_template_name.nil?
91
+ return assembly_template_name
92
+ end
93
+
94
+ def self.pretty_print_cols()
95
+ PPColumns.get(:assembly)
96
+ end
97
+
98
+
99
+ # List assembly templates for specific module
100
+ def self.validation_list(context_params)
101
+ if context_params.is_there_identifier?(:"service-module")
102
+ service_module_id = context_params.retrieve_arguments([:service_module_id!])
103
+ get_cached_response(:assembly, "service_module/list_assemblies", { :service_module_id => service_module_id })
104
+ else
105
+ get_cached_response(:assembly, "assembly/list", {:subtype => 'template' })
106
+ end
107
+ end
108
+
109
+ def self.assembly_list()
110
+ assembly_list = []
111
+ response = get_cached_response(:service, "assembly/list", {})
112
+ raise DTK::Client::DtkError, "Unable to retreive service list." unless (response.nil? || response.ok?)
113
+
114
+ if assemblies = response.data
115
+ assemblies.each do |assembly|
116
+ assembly_list << assembly["display_name"]
117
+ end
118
+ end
119
+
120
+ assembly_list
121
+ end
122
+
123
+ desc "ASSEMBLY-NAME/ID info", "Get information about given assembly."
124
+ method_option :list, :type => :boolean, :default => false
125
+ def info(context_params)
126
+ assembly_template_id = context_params.retrieve_arguments([:assembly_id!],method_argument_names)
127
+ data_type = :assembly_template
128
+
129
+ post_body = {
130
+ :assembly_id => assembly_template_id,
131
+ :subtype => 'template',
132
+ }
133
+
134
+ post rest_url("assembly/info"), post_body
135
+ end
136
+
137
+ desc "ASSEMBLY-NAME/ID list-nodes [--service SERVICE-NAME]", "List all nodes for given assembly."
138
+ method_option :list, :type => :boolean, :default => false
139
+ method_option "service",:aliases => "-s" ,
140
+ :type => :string,
141
+ :banner => "SERVICE-LIST-FILTER",
142
+ :desc => "Service list filter"
143
+ def list_nodes(context_params)
144
+ context_params.method_arguments = ["nodes"]
145
+ list(context_params)
146
+ end
147
+
148
+ desc "ASSEMBLY-NAME/ID list-components [--service SERVICE-NAME]", "List all components for given assembly."
149
+ method_option :list, :type => :boolean, :default => false
150
+ method_option "service",:aliases => "-s" ,
151
+ :type => :string,
152
+ :banner => "SERVICE-LIST-FILTER",
153
+ :desc => "Service list filter"
154
+ def list_components(context_params)
155
+ context_params.method_arguments = ["components"]
156
+ list(context_params)
157
+ end
158
+
159
+ # desc "[ASSEMBLY-TEMPLATE-NAME/ID] show [nodes|components|targets]", "List all nodes/components/targets for given assembly template."
160
+ #TODO: temporaily taking out target option
161
+ desc "list", "List all assemblies."
162
+ def list(context_params)
163
+ assembly_template_id, about, service_filter = context_params.retrieve_arguments([:assembly_id, :option_1, :option_1],method_argument_names)
164
+
165
+ if assembly_template_id.nil?
166
+
167
+ if options.service
168
+ service_id = options.service
169
+ context_params_for_service = DTK::Shell::ContextParams.new
170
+ context_params_for_service.add_context_to_params("service_module", "service_module", service_id)
171
+ context_params_for_service.method_arguments = ['assembly',"#{service_id}"]
172
+
173
+ response = DTK::Client::ContextRouter.routeTask("service_module", "list", context_params_for_service, @conn)
174
+ else
175
+ response = post rest_url("assembly/list"), {:subtype => 'template', :detail_level => 'nodes'}
176
+ data_type = :assembly_template
177
+ response.render_table(data_type) unless options.list?
178
+ return response
179
+ end
180
+
181
+ else
182
+
183
+ post_body = {
184
+ :subtype => 'template',
185
+ :assembly_id => assembly_template_id,
186
+ :about => about
187
+ }
188
+
189
+ case about
190
+ when 'nodes'
191
+ response = post rest_url("assembly/info_about"), post_body
192
+ data_type = :node_template
193
+ when 'components'
194
+ response = post rest_url("assembly/info_about"), post_body
195
+ data_type = :component
196
+ # when 'attributes'
197
+ # response = post rest_url("assembly/info_about"), post_body
198
+ # data_type = :attribute
199
+ else
200
+ raise_validation_error_method_usage('list')
201
+ end
202
+
203
+ response.render_table(data_type) unless options.list?
204
+
205
+ return response
206
+ end
207
+ end
208
+
209
+ desc "ASSEMBLY-NAME/ID stage [INSTANCE-NAME] [-t TARGET-NAME/ID]", "Stage assembly in target."
210
+ method_option "in-target",:aliases => "-t" ,
211
+ :type => :string,
212
+ :banner => "TARGET-NAME/ID",
213
+ :desc => "Target (id) to create assembly in"
214
+ def stage(context_params)
215
+ assembly_template_id, name = context_params.retrieve_arguments([:assembly_id!, :option_1],method_argument_names)
216
+ post_body = {
217
+ :assembly_id => assembly_template_id
218
+ }
219
+
220
+ assembly_template_name = get_assembly_name(assembly_template_id)
221
+ assembly_template_name.gsub!('::','-') if assembly_template_name
222
+
223
+ # we check current options and forwarded options (from deploy method)
224
+ in_target = options["in-target"] || context_params.get_forwarded_thor_option("in-target")
225
+ assembly_list = Assembly.assembly_list()
226
+
227
+ if name
228
+ raise DTK::Client::DtkValidationError, "Unable to stage service with name '#{name}'. Service with specified name exists already!" if assembly_list.include?(name)
229
+ else
230
+ name = get_assembly_stage_name(assembly_list,assembly_template_name)
231
+ end
232
+
233
+ post_body.merge!(:target_id => in_target) if in_target
234
+ post_body.merge!(:name => name) if name
235
+
236
+ response = post rest_url("assembly/stage"), post_body
237
+ return response unless response.ok?
238
+ # when changing context send request for getting latest assemblies instead of getting from cache
239
+ @@invalidate_map << :service
240
+ @@invalidate_map << :assembly
241
+
242
+ return response
243
+ end
244
+
245
+ # desc "ASSEMBLY-NAME/ID deploy [-v VERSION] [INSTANCE-NAME] [-t TARGET-NAME/ID] [-m COMMIT-MSG]", "Stage and deploy assembly in target."
246
+ # version_method_option
247
+ desc "ASSEMBLY-NAME/ID deploy [INSTANCE-NAME] [-t TARGET-NAME/ID] [-m COMMIT-MSG]", "Stage and deploy assembly in target."
248
+ method_option "in-target",:aliases => "-t" ,
249
+ :type => :string,
250
+ :banner => "TARGET-NAME/ID",
251
+ :desc => "Target (id) to create assembly in"
252
+ method_option "commit_msg",:aliases => "-m" ,
253
+ :type => :string,
254
+ :banner => "COMMIT-MSG",
255
+ :desc => "Commit message"
256
+ def deploy(context_params)
257
+ context_params.forward_options(options)
258
+ response = stage(context_params)
259
+
260
+ return response unless response.ok?
261
+
262
+ # create task
263
+ # commented assemlby_id until we implement json to yaml parsing on client side instead of server side
264
+ # assembly_id = response.data(:assembly_id)
265
+
266
+ # temp solution just to make deploy to work, since response we get from 'stage' command is simple string presented as yaml
267
+ assembly_id = response.data.match(/(id:)\s*(\d+)/)[2]
268
+
269
+ post_body = {
270
+ :assembly_id => assembly_id,
271
+ :commit_msg => options["commit_msg"]||"Initial deploy"
272
+ }
273
+
274
+ response = post rest_url("assembly/find_violations"), post_body
275
+ return response unless response.ok?
276
+ if response.data and response.data.size > 0
277
+ error_message = "The following violations were found; they must be corrected before the assembly can be deployed"
278
+ DTK::Client::OsUtil.print(error_message, :red)
279
+ return response.render_table(:violation)
280
+ end
281
+
282
+ ret = response = post(rest_url("assembly/create_task"), post_body)
283
+
284
+ return response unless response.ok?
285
+
286
+ # execute task
287
+ task_id = response.data(:task_id)
288
+ response = post(rest_url("task/execute"), "task_id" => task_id)
289
+
290
+ # start watching task ID
291
+ if $shell_mode
292
+ DTK::Shell::StatusMonitor.start_monitoring(task_id) if response.ok?
293
+ end
294
+
295
+ return response unless response.ok?
296
+ ret.add_data_value!(:task_id,task_id)
297
+
298
+ # when changing context send request for getting latest assemblies instead of getting from cache
299
+ @@invalidate_map << :service
300
+
301
+ return ret
302
+ end
303
+
304
+
305
+ desc "delete ASSEMBLY-ID", "Delete assembly"
306
+ method_option :force, :aliases => '-y', :type => :boolean, :default => false
307
+ def delete(context_params)
308
+ assembly_template_id = context_params.retrieve_arguments([:option_1!],method_argument_names)
309
+ unless options.force?
310
+ # Ask user if really want to delete assembly-template, if not then return to dtk-shell without deleting
311
+ return unless Console.confirmation_prompt("Are you sure you want to delete assembly '#{assembly_template_id}'"+"?")
312
+ end
313
+
314
+ post_body = {
315
+ :assembly_id => assembly_template_id,
316
+ :subtype => :template
317
+ }
318
+ response = post rest_url("assembly/delete"), post_body
319
+
320
+ # when changing context send request for getting latest assemblies instead of getting from cache
321
+ @@invalidate_map << :assembly
322
+ return response unless response.ok?
323
+ module_name,branch = response.data(:module_name,:workspace_branch)
324
+ response = Helper(:git_repo).pull_changes?(:service_module,module_name,:local_branch => branch)
325
+ return response unless response.ok?()
326
+ Response::Ok.new()
327
+ end
328
+ end
329
+ end
@@ -0,0 +1,62 @@
1
+
2
+ module DTK::Client
3
+ class Attribute < CommandBaseThor
4
+
5
+ no_tasks do
6
+
7
+ def self.assembly_validation_list(context_params)
8
+ assembly_or_worspace_id, node_id, component_id = context_params.retrieve_arguments([[:service_id!, :workspace_id!], :node_id!, :component_id!])
9
+
10
+ post_body = {
11
+ :assembly_id => assembly_or_worspace_id,
12
+ :node_id => node_id,
13
+ :component_id => component_id,
14
+ :subtype => 'instance',
15
+ :about => 'attributes',
16
+ :filter => nil
17
+ }
18
+
19
+ response = get_cached_response(:service_node_component_attribute, "assembly/info_about", post_body)
20
+ modified_response = response.clone_me()
21
+
22
+ modified_response['data'].each { |e| e['display_name'] = e['display_name'].split('/').last }
23
+
24
+ return modified_response
25
+ end
26
+
27
+ def self.module_validation_list(context_params)
28
+ component_module_id = context_params.retrieve_arguments([:module_id!])
29
+
30
+ post_body = {
31
+ :component_module_id => component_module_id,
32
+ :about => :attributes
33
+ }
34
+ response = post rest_url("component_module/info_about"), post_body
35
+
36
+ modified_response = response.clone_me()
37
+ modified_response['data'].each { |e| e['display_name'] = e['display_name'].split('/').last }
38
+ #modified_response['data'].each { |e| e['display_name'] = e['display_name'].match(/.+\[.+::(.*)\]/)[1] }
39
+
40
+ return modified_response
41
+ end
42
+
43
+ end
44
+
45
+ def self.validation_list(context_params)
46
+ command_name = context_params.root_command_name
47
+
48
+ case command_name
49
+ when 'service'
50
+ return assembly_validation_list(context_params)
51
+ when 'workspace'
52
+ return assembly_validation_list(context_params)
53
+ when 'module'
54
+ return module_validation_list(context_params)
55
+ else
56
+ raise DTK::Client::DtkError,"Attribute 'validation_list' not supported for #{command_name}, implementation nedeed."
57
+ end
58
+ end
59
+
60
+
61
+ end
62
+ end