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,221 @@
1
+ class Thor
2
+ class << self
3
+ # NOTE: Class is loaded automaticly in dtk-shell
4
+
5
+ @@shell_context = nil
6
+ HIDE_FROM_BASE_CONTEXT_HELP = "HIDE_FROM_BASE"
7
+
8
+ def set_context(context)
9
+ @@shell_context = context
10
+ end
11
+
12
+ def match_help_item_changes(help_item, entity_name)
13
+ help_item.first.match(/^\[?#{entity_name.upcase}.?(NAME\/ID|ID\/NAME|ID|NAME)(\-?PATTERN)?\]?/)
14
+ end
15
+
16
+ def replace_if_matched!(help_item, matched)
17
+ # change by reference
18
+ help_item.first.gsub!(matched[0],'') if matched
19
+
20
+ return help_item
21
+ end
22
+
23
+ # Method returns alternative providers
24
+ def get_alternative_identifiers(command_name)
25
+ # we check for alternate identifiers
26
+ command_clazz = ::DTK::Client::OsUtil.get_dtk_class(command_name)
27
+
28
+ if (command_clazz && command_clazz.respond_to?(:alternate_identifiers))
29
+ return command_clazz.alternate_identifiers()
30
+ end
31
+
32
+ return []
33
+ end
34
+
35
+ # Monkey path of printable task methods to include name as well
36
+ # Returns tasks ready to be printed.
37
+ def printable_tasks(all = true, subcommand = false)
38
+ (all ? all_tasks : tasks).map do |_, task|
39
+ # using HIDE_FROM_BASE to hide command from base context help (e.g from dtk:/assembly>help) ...
40
+ # but show that command in other context help (e.g in dtk:/assembly/assembly_id/utils>help)
41
+ # added (task.name.eql?('help')) to hide help from command list
42
+ next if (task.hidden? || (task.name.eql?("help")) || (task.usage.include?(HIDE_FROM_BASE_CONTEXT_HELP) && (@@shell_context ? !@@shell_context.active_context.is_n_context? : '')))
43
+ item = []
44
+ item << banner(task, false, subcommand)
45
+ item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "")
46
+ item << task.name
47
+ item
48
+ end.compact
49
+ end
50
+
51
+ # method will check if help is overriden and if so it will replace help description,
52
+ # with overriden one, override_tasks => class => OverrideTasks
53
+ def overriden_help(override_tasks, help_item, is_command)
54
+ return (override_tasks && override_tasks.are_there_self_override_tasks?) ? override_tasks.check_help_item(help_item, is_command) : help_item
55
+ end
56
+
57
+ def help(shell, subcommand = false)
58
+ list = printable_tasks(true, subcommand)
59
+
60
+ Thor::Util.thor_classes_in(self).each do |klass|
61
+ list += klass.printable_tasks(false)
62
+ end
63
+
64
+ list.sort!{ |a,b| a[0] <=> b[0] }
65
+
66
+ # monkey patching here => START
67
+ if @@shell_context
68
+ unless @@shell_context.root?
69
+
70
+ # first command we are using:
71
+ # e.g. dtk:\assembly\assembly1\node\node123> => command would be :assembly
72
+ command = @@shell_context.active_context.first_command_name.upcase
73
+
74
+ # is there identifier for given commands (first)
75
+ # e.g. dtk:\assembly\assembly1\node\node123> => identifier here would be 'assembly1'
76
+ is_there_identifier = @@shell_context.active_context.is_there_identifier_for_first_context?
77
+
78
+ # alternative providers
79
+ alt_identifiers = get_alternative_identifiers(command)
80
+
81
+
82
+ filtered_list = []
83
+
84
+ # case when we are not on first level and it is not identifier we skip help
85
+ # since it needs to be empty
86
+ # e.g. assembly/bootstrap1/node> ... HELP IS EMPTY FOR THIS
87
+
88
+
89
+ # override objects are special cases defined in Thor classes
90
+ # base on level there will be included in help context, help content is calculated by:
91
+ #
92
+ # 1) Matching help items with Regex (see bellow)
93
+ # 2) Adding help items from override_methods
94
+ #
95
+ #
96
+ override_tasks_obj = self.respond_to?(:override_allowed_methods) ? self.override_allowed_methods.dup : nil
97
+
98
+ # N-LEVEL-CONTEXT - context that has at least 2 commands and 1 or more identifiers
99
+ # e.g. dtk:\assembly\assembly1\node> THIS IS N-LEVEL CONTEXT
100
+ # e.g. dtk:\assembly\assembly1\node\node123> THIS IS N-LEVEL CONTEXT
101
+ # e.g. dtk:\assembly\assembly1> THIS IS NOT N-LEVEL CONTEXT
102
+ #
103
+ if (!@@shell_context.active_context.is_n_context? || @@shell_context.active_context.current_identifier?)
104
+
105
+ list.each do |help_item|
106
+ help_item.first.gsub!("^^", '') if help_item.first.include?("^^")
107
+
108
+ # this will match entity_name (command) and alternative identifiers
109
+ identifers = [command] + alt_identifiers
110
+
111
+ # matches identifiers for ID/NAME
112
+ matched_data = help_item.first.match(/^\s\[?(#{identifers.join('|')}).?(NAME\/ID|ID\/NAME)\]?\s/)
113
+ alt_matched_data = help_item.first.match(/^\s\[?(#{alt_identifiers.join('|')}).?(NAME\/ID|ID\/NAME)\]?\s/)
114
+
115
+ if matched_data.nil?
116
+ # not found and tier 1 we add it to help list
117
+ filtered_list << overriden_help(override_tasks_obj, help_item, true) if @@shell_context.current_command?
118
+ else
119
+ # for help we only care about first context name / identifier
120
+ if !is_there_identifier
121
+ # if it contains [] it is optional and will be available on both tiers
122
+ if matched_data[0].include?('[')
123
+ # we remove it, since there is no need to use it
124
+ help_item.first.gsub!(matched_data[0],' ') unless help_item.nil?
125
+ filtered_list << overriden_help(override_tasks_obj, help_item, true)
126
+ end
127
+ else
128
+ # Adding alt identifiers here
129
+ if alt_matched_data
130
+ if @@shell_context.active_context.current_alt_identifier?
131
+ help_item.first.gsub!(matched_data[0],'') unless help_item.nil?
132
+ filtered_list << overriden_help(override_tasks_obj, help_item, false)
133
+ end
134
+ else
135
+ unless @@shell_context.active_context.current_alt_identifier?
136
+ help_item.first.gsub!(matched_data[0],'') unless help_item.nil?
137
+ filtered_list << overriden_help(override_tasks_obj, help_item, false)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ # This will return commands that have identifiers
146
+ # e.g. dtk:\assembly\assembly1\node\node123> => ['assembly','node']
147
+ commands_that_have_identifiers = @@shell_context.active_context.commands_that_have_identifiers()
148
+ is_n_level_context = @@shell_context.active_context.command_list.size > 1
149
+
150
+ # first one does not count
151
+ if is_n_level_context
152
+ # additional filter list for n-context
153
+ n_filter_list = []
154
+ # we do not need first one, since above code takes care of that one
155
+ filtered_list = filtered_list.select do |filtered_help_item|
156
+ #next unless filtered_help_item
157
+ commands_that_have_identifiers[1..-1].each_with_index do |entity,i|
158
+ matched = match_help_item_changes(filtered_help_item, entity)
159
+ filtered_help_item = replace_if_matched!(filtered_help_item, matched)
160
+
161
+ # if it is last command, and there were changes
162
+ if (i == (commands_that_have_identifiers.size - 2) && matched)
163
+ n_filter_list << filtered_help_item
164
+ end
165
+ end
166
+ end
167
+
168
+ if override_tasks_obj && is_n_level_context
169
+ last_entity_name = @@shell_context.active_context.last_context_entity_name.to_sym
170
+
171
+ # we get commands task, and identifier tasks for given entity (e.g. :assembly)
172
+ command_o_tasks, identifier_o_tasks = override_tasks_obj.get_all_tasks(last_entity_name)
173
+
174
+ if @@shell_context.active_context.current_identifier?
175
+ identifier_o_tasks.each do |o_task|
176
+ n_filter_list << [o_task[1],o_task[2]]
177
+ end
178
+ else
179
+ command_o_tasks.each do |o_task|
180
+ n_filter_list << [o_task[1],o_task[2]]
181
+ end
182
+ end
183
+ end
184
+
185
+ # we have just filtered those methods that have attribute for given entity
186
+ # and also are last in the list
187
+ filtered_list = n_filter_list
188
+ end
189
+
190
+ # remove double spaces
191
+ list = filtered_list.each { |e| e.first.gsub!(/ /,' ') }
192
+ end
193
+ else
194
+ # no dtk-shell just dtk, we make sure that underscore is not used '_'
195
+ list = list.collect do |item|
196
+
197
+ #
198
+ # e.g.
199
+ # dtk assembly_template info
200
+ # dtk assembly-template info
201
+ #
202
+ item[0] = item[0].gsub(/^dtk ([a-zA-Z]+)_([a-zA-Z]+) /,'dtk \1-\2 ')
203
+ item
204
+ end
205
+ end
206
+
207
+ if list.empty?
208
+ shell.say ""
209
+ shell.say "No tasks for current context '#{@@shell_context.active_context.full_path}'."
210
+ end
211
+
212
+ # remove helper 3. element in help item list
213
+ list = list.collect { |e| e[0..1] }
214
+
215
+ # monkey patching here => END
216
+ shell.print_table(list, :indent => 2, :truncate => true)
217
+ shell.say
218
+ class_options_help(shell)
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,233 @@
1
+ require 'colorize'
2
+ require 'readline'
3
+
4
+ module DTK
5
+ module Shell
6
+
7
+
8
+ # we use interactive wizard to give user opertunity
9
+ class InteractiveWizard
10
+
11
+ PP_LINE_HEAD = '--------------------------------- DATA ---------------------------------'
12
+ PP_LINE = '------------------------------------------------------------------------'
13
+ INVALID_INPUT = Client::OsUtil.colorize(" Input is not valid.", :yellow)
14
+ EC2_REGIONS = ['us-east-1','us-west-1','us-west-2','eu-west-1','sa-east-1','ap-northeast-1','ap-southeast-1','ap-southeast-2' ]
15
+
16
+
17
+ def initialize
18
+ end
19
+
20
+ def self.validate_region(region)
21
+ unless EC2_REGIONS.include? region
22
+ raise ::DTK::Client::DtkValidationError.new("Region '#{region}' is not EC2 region, use one of: #{EC2_REGIONS.join(',')}")
23
+ end
24
+ end
25
+
26
+ # Generic wizard which will return hash map based on metadata input
27
+ def self.interactive_user_input(wizard_dsl, recursion_call = false)
28
+ results = {}
29
+
30
+ begin
31
+ wizard_dsl.each do |meta_input|
32
+ input_name = meta_input.keys.first
33
+ display_name = input_name.to_s.gsub(/_/,' ')
34
+ metadata = meta_input.values.first
35
+ case metadata[:type]
36
+ when nil
37
+ output = recursion_call ? "#{display_name.capitalize}: " : "Enter value for '#{display_name}': "
38
+ validation = nil
39
+ when :question
40
+ output = "#{metadata[:question]} (#{metadata[:options].join('|')}): "
41
+ validation =
42
+ metadata[:options]
43
+ when :selection
44
+ options = ""
45
+ display_field = metadata[:display_field]
46
+ metadata[:options].each_with_index do |o,i|
47
+ if display_field
48
+ options += "\t#{i+1}. #{o[display_field]}\n"
49
+ else
50
+ options += "\t#{i+1}. #{o}\n"
51
+ end
52
+ end
53
+ options += DTK::Client::OsUtil.colorize("\t0. Skip\n", :yellow) if metadata[:skip_option]
54
+ output = "Select '#{display_name}': \n\n #{options} \n "
55
+ validation_range_start = metadata[:skip_option] ? 0 : 1
56
+ validation = (validation_range_start..metadata[:options].size).to_a
57
+ when :group
58
+ # recursion call to populate second level of hash params
59
+ puts " Enter '#{display_name}' details: "
60
+ results[input_name] = self.interactive_user_input(metadata[:options], true)
61
+ next
62
+ end
63
+
64
+ input = resolve_input(output,validation,!metadata[:optional],recursion_call)
65
+
66
+ if metadata[:required_options] && !metadata[:required_options].include?(input)
67
+ # case where we have to give explicit permission, if answer is not affirmative
68
+ # we terminate rest of the wizard
69
+ DTK::Client::OsUtil.print(" #{metadata[:explanation]}", :red)
70
+ return nil
71
+ end
72
+
73
+ # post processing
74
+ if metadata[:type] == :selection
75
+ input = input.to_i == 0 ? nil : metadata[:options][input.to_i - 1]
76
+ end
77
+
78
+ results[input_name] = input
79
+ end
80
+
81
+ return results
82
+ rescue Interrupt => e
83
+ puts
84
+ raise DTK::Client::DtkValidationError, "Exiting the wizard ..."
85
+ end
86
+ end
87
+
88
+
89
+ def self.resolve_input(output, validation, is_required, is_recursion_call)
90
+ tab_prefix = is_recursion_call ? "\t" : ""
91
+
92
+ # there was a bug within windows that does not support multiline input in readline method
93
+ # following is the fix
94
+ prompt_input = " #{tab_prefix}#{output}"
95
+ if output.match(/\n/)
96
+ puts prompt_input
97
+ prompt_input = ">> "
98
+ end
99
+
100
+ while line = Readline.readline(prompt_input, true)
101
+ if is_required && line.empty?
102
+ puts INVALID_INPUT
103
+ next
104
+ end
105
+
106
+ if !validation || validation.find { |val| line.eql?(val.to_s) }
107
+ return line
108
+ end
109
+
110
+ puts INVALID_INPUT
111
+ end
112
+ end
113
+
114
+
115
+
116
+ # takes hash maps with description of missing params and
117
+ # returns array of hash map with key, value for each missed param
118
+ def self.resolve_missing_params(param_list)
119
+ begin
120
+ user_provided_params, checkup_hash = [], {}
121
+
122
+ puts "\nPlease fill in missing data.\n"
123
+ param_list.each do |param_info|
124
+ description =
125
+ if param_info['display_name'] =~ Regexp.new(param_info['description'])
126
+ param_info['display_name']
127
+ else
128
+ "#{param_info['display_name']} (#{param_info['description']})"
129
+ end
130
+ datatype_info = (param_info['datatype'] ? DTK::Client::OsUtil.colorize(" [#{param_info['datatype'].upcase}]", :yellow) : '')
131
+ string_identifier = DTK::Client::OsUtil.colorize(description, :green) + datatype_info
132
+
133
+ puts "Please enter #{string_identifier}:"
134
+ while line = Readline.readline(": ", true)
135
+ id = param_info['id']
136
+ user_provided_params << {:id => id, :value => line}
137
+ checkup_hash[id] = {:value => line, :description => description}
138
+ break
139
+ end
140
+
141
+ end
142
+
143
+ # pp print for provided parameters
144
+ pretty_print_provided_user_info(checkup_hash)
145
+
146
+ # make sure this is satisfactory
147
+ while line = Readline.readline("Is provided information ok? (yes|no) ", true)
148
+ # start all over again
149
+ return resolve_missing_params(param_list) if 'no'.eql? line
150
+ # continue with the code
151
+ break if 'yes'.eql? line
152
+ end
153
+
154
+ rescue Interrupt => e
155
+ puts
156
+ # TODO: Provide original error here
157
+ raise DTK::Client::DtkError, "You have decided to skip correction wizard."
158
+ end
159
+
160
+ return user_provided_params
161
+ end
162
+
163
+ private
164
+
165
+ def self.pretty_print_provided_user_info(user_information)
166
+ puts PP_LINE_HEAD
167
+ user_information.each do |key,info|
168
+ description = info[:description]
169
+ value = info[:value]
170
+ printf "%48s : %s\n", DTK::Client::OsUtil.colorize(description, :green), DTK::Client::OsUtil.colorize(value, :yellow)
171
+ end
172
+ puts PP_LINE
173
+ puts
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ ## EXAMPLE OF USAGE
180
+
181
+ # Example 1. Creating target via wizard
182
+ =begin
183
+ desc "create","Wizard that will guide you trough creation of target and target-template"
184
+ def create(context_params)
185
+
186
+ # we get existing templates
187
+ target_templates = post rest_url("target/list"), { :subtype => :template }
188
+
189
+ # ask user to select target template
190
+ wizard_params = [{:target_template => { :type => :selection, :options => target_templates['data'], :display_field => 'display_name', :skip_option => true }}]
191
+ target_template_selected = DTK::Shell::InteractiveWizard.interactive_user_input(wizard_params)
192
+ target_template_id = (target_template_selected[:target_template]||{})['id']
193
+
194
+ wizard_params = [
195
+ {:target_name => {}},
196
+ {:description => {:optional => true }}
197
+ ]
198
+
199
+ if target_template_id.nil?
200
+ # in case user has not selected template id we will needed information to create target
201
+ wizard_params.concat([
202
+ {:iaas_type => { :type => :selection, :options => [:ec2] }},
203
+ {:aws_install => { :type => :question,
204
+ :question => "Do we have your permission to add necessery 'key-pair' and 'security-group' to your EC2 account?",
205
+ :options => ["yes","no"],
206
+ :required_options => ["yes"],
207
+ :explanation => "This permission is necessary for creation of a custom target."
208
+ }},
209
+ {:iaas_properties => { :type => :group, :options => [
210
+ {:key => {}},
211
+ {:secret => {}},
212
+ {:region => {:type => :selection, :options => DTK::Shell::InteractiveWizard::EC2_REGIONS}},
213
+ ]}},
214
+ ])
215
+ end
216
+
217
+ post_body = DTK::Shell::InteractiveWizard.interactive_user_input(wizard_params)
218
+ post_body ||= {}
219
+
220
+ # this means that user has not given permission so we skip request
221
+ return unless (target_template_id || post_body[:aws_install])
222
+
223
+ # in case user chose target ID
224
+ post_body.merge!(:target_template_id => target_template_id) if target_template_id
225
+
226
+
227
+ response = post rest_url("target/create"), post_body
228
+ # when changing context send request for getting latest targets instead of getting from cache
229
+ @@invalidate_map << :target
230
+
231
+ return response
232
+ end
233
+ =end
@@ -0,0 +1,22 @@
1
+ class Thor
2
+ class Options < Arguments #:nodoc:
3
+
4
+ protected
5
+
6
+ def parse_boolean(switch)
7
+ if current_is_value?
8
+ if ["true", "TRUE", "t", "T", true].include?(peek)
9
+ # shift
10
+ true
11
+ elsif ["false", "FALSE", "f", "F", false].include?(peek)
12
+ # shift
13
+ true
14
+ else
15
+ true
16
+ end
17
+ else
18
+ @switches.key?(switch) || !no_or_skip?(switch)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,105 @@
1
+ require 'thread'
2
+ require 'singleton'
3
+ require 'colorize'
4
+ #dtk_require('../commands')
5
+
6
+ # This singleton is used to check status on running processes on the server side
7
+ # Once certain task is complete it will give notice to user da certain task has been completed
8
+ # At the moment this only
9
+
10
+ module DTK
11
+ module Shell
12
+ class TaskStatusThread < Thread
13
+ attr_accessor :task_id, :finished, :status
14
+
15
+ def initialize
16
+ @finished = false
17
+ super
18
+ end
19
+ end
20
+
21
+ class StatusMonitor
22
+ include Singleton
23
+ include DTK::Client::CommandBase
24
+
25
+ THREAD_SLEEP_TIME = DTK::Configuration.get(:task_check_frequency)
26
+
27
+ def initialize
28
+ @threads = []
29
+ @finished_tasks = []
30
+ @conn = DTK::Client::Session.get_connection()
31
+ end
32
+
33
+ def self.start_monitoring(task_id)
34
+ self.instance.start_monitoring(task_id)
35
+ end
36
+
37
+ def self.check_status
38
+ self.instance.check_status
39
+ end
40
+
41
+ def check_status
42
+ @threads.each do |t|
43
+ if t.finished
44
+ @finished_tasks << t
45
+ end
46
+ end
47
+
48
+ # removes finished tasks from the main queue
49
+ @threads = @threads - @finished_tasks
50
+
51
+ @finished_tasks.each do |t|
52
+ puts ""
53
+ puts "[TASK NOTICE] Task with ID: #{t.task_id}, has finished with status: #{colorize_status(t.status)}"
54
+ end
55
+
56
+ @finished_tasks.clear
57
+ end
58
+
59
+ def start_monitoring(task_id)
60
+ puts "Client has started monitoring task [ID:#{task_id}]. You will be notified when task has been completed."
61
+ @threads << DTK::Shell::TaskStatusThread.new do
62
+ begin
63
+ response, post_hash_body = nil, {}
64
+ post_hash_body[:task_id] = task_id
65
+ DTK::Shell::TaskStatusThread.current.task_id = task_id
66
+
67
+ # pooling server for task status
68
+ while task_running?(response)
69
+ sleep(THREAD_SLEEP_TIME) unless response.nil?
70
+ response = post rest_url("task/status"),post_hash_body
71
+ # we break if there is error in response
72
+ break unless response.ok?
73
+ end
74
+
75
+ DTK::Shell::TaskStatusThread.current.finished = true
76
+
77
+ if response.ok?
78
+ DTK::Shell::TaskStatusThread.current.status = response.data['status'].upcase
79
+ else
80
+ DTK::Shell::TaskStatusThread.current.status = "RESPONSE NOT OK, RESPONSE: #{response}"
81
+ end
82
+
83
+ rescue Exception => e
84
+ DtkLogger.instance.error_pp("[THREAD ERROR] Error getting task status with message: #{e.message}", e.backtrace)
85
+ end
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def colorize_status(status)
92
+ color = status.eql?('FAILED') ? :red : :green
93
+ return DTK::Client::OsUtil.colorize(status, color)
94
+ end
95
+
96
+ # return true if status SUCCEDED, FAILED
97
+ # returns false if status EXECUTING
98
+ def task_running?(response)
99
+ return true if response.nil?
100
+ return !(response.data['status'].eql?("succeeded") || response.data['status'].eql?("failed"))
101
+ end
102
+
103
+ end
104
+ end
105
+ end