Top Level Namespace
Defined Under Namespace
Modules: Bundler, DTK, DtkShell Classes: DiskCacher, DtkLogger, DtkOpenStruct, MainContext, PPColumns, String, Thor
Constant Summary collapse
- ALIAS_COMMANDS =
{ 'ls' => 'list', 'cd' => 'cc', 'rm' => 'delete' }
- POSSIBLE_COMMON_CORE_FOLDERS =
we leave possibilites that folders user multiple names when somebody takes fresh projects from git it is expected that person will use dtk-common name
['dtk-common-repo','dtk-common-core']
- DEFAULT_COMMIT_MSG =
"Initial commit."
- PULL_CATALOGS =
["dtkn"]
- LOG_SLEEP_TIME_W =
DTK::Configuration.get(:tail_log_frequency)
Instance Method Summary collapse
- #dtk_nested_require(dir, *files_x) ⇒ Object
- #dtk_require(*files_x) ⇒ Object
- #dtk_require_common_commands(*files_x) ⇒ Object
- #dtk_require_dtk_common_core(common_library) ⇒ Object
- #dtk_require_from_base(*files_x) ⇒ Object
- #execute_shell_command(line, prompt) ⇒ Object
- #execute_shell_command_internal(line) ⇒ Object
-
#gem_only_available? ⇒ Boolean
this returns true if there is no common folder e.g.
- #init_shell_context ⇒ Object
- #load_command(command_name) ⇒ Object
-
#preprocess_commands(original_command) ⇒ Object
support for alias commands (ls for list, cd for cc etc.).
- #print_method_response!(response_ruby_obj) ⇒ Object
-
#resolve_direct_access(params, config_exists = nil) ⇒ Object
check if .add_direct_access file exists, if not then add direct access and create .add_direct_access file.
-
#run_shell_command ⇒ Object
RUNTIME PART - STARTS HERE.
- #top_level_execute(entity_name, method_name, context_params = nil, options_args = nil, shell_execute = false) ⇒ Object
- #top_level_execute_core(entity_name, method_name, context_params = nil, options_args = nil, shell_execute = false) ⇒ Object
-
#validate_connection(connection) ⇒ Object
check if connection is set up properly.
Instance Method Details
#dtk_nested_require(dir, *files_x) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/require_first.rb', line 41 def dtk_nested_require(dir,*files_x) files = (files_x.first.kind_of?(Array) ? files_x.first : files_x) caller_dir = caller.first.gsub(/\/[^\/]+$/,"") # invalid command will be send here as such needs to be handled. # we will throw DtkClient error as invalid command files.each do |f| begin require File.("#{dir}/#{f}",caller_dir) rescue LoadError => e if e..include? "#{dir}/#{f}" raise DTK::Client::DtkError,"Command '#{f}' not found." else raise e end end end end |
#dtk_require(*files_x) ⇒ Object
26 27 28 29 30 |
# File 'lib/require_first.rb', line 26 def dtk_require(*files_x) files = (files_x.first.kind_of?(Array) ? files_x.first : files_x) caller_dir = caller.first.gsub(/\/[^\/]+$/,"") files.each{|f|require File.(f,caller_dir)} end |
#dtk_require_common_commands(*files_x) ⇒ Object
37 38 39 |
# File 'lib/require_first.rb', line 37 def dtk_require_common_commands(*files_x) dtk_require_from_base(*files_x.map{|f|"commands/common/#{f}"}) end |
#dtk_require_dtk_common_core(common_library) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/require_first.rb', line 66 def dtk_require_dtk_common_core(common_library) # use common folder else common gem common_folder = determine_common_folder() if common_folder dtk_require("../../" + common_folder + "/lib/#{common_library}") elsif is_dtk_common_core_gem_installed? # already loaded so do not do anything else raise DTK::Client::DtkError,"Common directory/gem not found, please make sure that you have cloned dtk-common folder or installed dtk common gem!" end end |
#dtk_require_from_base(*files_x) ⇒ Object
32 33 34 35 |
# File 'lib/require_first.rb', line 32 def dtk_require_from_base(*files_x) #different than just calling dtk_require because of change to context give by caller dtk_require(*files_x) end |
#execute_shell_command(line, prompt) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/shell.rb', line 126 def execute_shell_command(line, prompt) begin # remove single/double quotes from string because shellwords module is not able to parse it if matched = line.scan(/['"]/) line.gsub!(/['"]/, '') if matched.size.odd? end # some special cases raise DTK::Shell::ExitSignal if line == 'exit' return prompt if line.empty? if line == 'clear' DTK::Client::OsUtil::clear_screen return prompt end # when using help on root this is needed line = 'dtk help' if (line == 'help' && MainContext.get_context.root?) args = Shellwords.split(line) cmd = args.shift # support command alias (ls for list etc.) cmd = preprocess_commands(cmd) # DEV only reload shell if ::DTK::Configuration.get(:development_mode) if ('restart' == cmd) puts "DEV Reloading shell ..." ::DTK::Client::OsUtil.dev_reload_shell() return prompt end end if ('cc' == cmd) # in case there is no params we just reload command args << "/" if args.empty? prompt = MainContext.get_context.change_context(args, cmd) elsif ('popc' == cmd) MainContext.get_context.dirs.shift() args << (MainContext.get_context.dirs.first.nil? ? '/' : MainContext.get_context.dirs.first) prompt = MainContext.get_context.change_context(args, cmd) elsif ('pushc' == cmd) if args.empty? args << (MainContext.get_context.dirs[1].nil? ? '/' : MainContext.get_context.dirs[1]) MainContext.get_context.dirs.unshift(args.first) MainContext.get_context.dirs.uniq! prompt = MainContext.get_context.change_context(args, cmd) else prompt = MainContext.get_context.change_context(args) # using regex to remove dtk: and > from path returned by change_context # e.g transform dtk:/assembly/node> to /assembly/node full_path = prompt.match(/[dtk:](\/.*)[>]/)[1] MainContext.get_context.dirs.unshift(full_path) end elsif ('dirs' == cmd) puts MainContext.get_context.dirs.inspect else # get all next-context-candidates (e.g. for assembly get all assembly_names) context_candidates = MainContext.get_context.get_ac_candidates_for_context(MainContext.get_context.active_context.last_context(), MainContext.get_context.active_context()) # this part of the code is used for calling of nested commands from base context (dtk:/>assembly/assembly_id converge) # base_command is used to check if first command from n-level is valid e.g. # (dtk:/>assembly/assembly_id converge - chech if 'assembly' exists in context_candidates) # revert_context is used to return to context which command is called from after command is executed base_command = cmd.split('/').first revert_context = false if context_candidates.include?(base_command) MainContext.get_context.change_context([cmd]) cmd = args.shift revert_context = true end if cmd.nil? prompt = MainContext.get_context.change_context(["-"]) if revert_context raise DTK::Client::DtkValidationError, "You have to provide command after context name. Usage: CONTEXT-TYPE/CONTEXT-NAME COMMAND [ARG1] .. [ARG2]." end # send monkey patch class information about context Thor.set_context(MainContext.get_context) # we get command and hash params, will return Validation error if command is not valid entity_name, method_name, context_params, , = MainContext.get_context.get_command_parameters(cmd,args) # check if command is executed from parent context (e.g assembly_name list-nodes) if context_candidates.include?(method_name) context_params.add_context_to_params(method_name, entity_name, method_name) method_name = context_params.method_arguments.shift if context_params.method_arguments.size > 0 else unless MainContext.get_context.method_valid?(method_name) prompt = MainContext.get_context.change_context(["-"]) if revert_context raise DTK::Client::DtkValidationError, "Method '#{method_name}' is not valid in current context." end end # raise validation error if option is not valid raise DTK::Client::DtkValidationError.new("Option '#{.first||method_name}' is not valid for current command!", true) unless .empty? # execute command via Thor current_contex_path = MainContext.get_context.active_context.full_path top_level_execute(entity_name, method_name, context_params, , true) # when 'delete' or 'delete-and-destroy' command is executed reload cached tasks with latest commands unless (args.nil? || args.empty?) MainContext.get_context.reload_cached_tasks(entity_name) if (method_name.include?('delete') || method_name.include?('import')) end # check execution status, prints status to sttout DTK::Shell::StatusMonitor.check_status() # if we change context while executing command, change prompt as well unless current_contex_path.eql?(MainContext.get_context.active_context.full_path) prompt = "dtk:#{MainContext.get_context.active_context.full_path}>" end # after nested command called from base context is executed successfully, return to context which command is executed from # this is the same as 'cd -' command is executed prompt = MainContext.get_context.change_context(["-"]) if revert_context end rescue DTK::Client::DSLParsing => e DTK::Client::OsUtil.print(e., :red) rescue DTK::Client::DtkValidationError => e DTK::Client::OsUtil.print(e., :yellow) rescue DTK::Shell::Error => e DtkLogger.instance.error(e., true) end return prompt end |
#execute_shell_command_internal(line) ⇒ Object
259 260 261 |
# File 'lib/shell.rb', line 259 def execute_shell_command_internal(line) execute_shell_command(line, DTK::Shell::Context::DTK_ROOT_PROMPT) end |
#gem_only_available? ⇒ Boolean
this returns true if there is no common folder e.g. dtk-common in parent folder, and gem is installed
62 63 64 |
# File 'lib/require_first.rb', line 62 def gem_only_available?() return !determine_common_folder() && is_dtk_common_core_gem_installed? end |
#init_shell_context ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/shell.rb', line 105 def init_shell_context() begin # @context = DTK::Shell::Context.new @shell_header = DTK::Shell::HeaderShell.new # loads root context MainContext.get_context.load_context() @t1 = nil Readline.completion_append_character='' DTK::Shell::Context.load_session_history().each do |c| Readline::HISTORY.push(c) end rescue DTK::Client::DtkError => e DtkLogger.instance.error(e., true) puts "Exiting ..." raise DTK::Shell::ExitSignal end end |
#load_command(command_name) ⇒ Object
137 138 139 140 141 142 |
# File 'lib/core.rb', line 137 def load_command(command_name) parser_adapter = DTK::Client::Config[:cli_parser] || "thor" dtk_nested_require("parser/adapters",parser_adapter) dtk_nested_require("commands/#{parser_adapter}",command_name) end |
#preprocess_commands(original_command) ⇒ Object
support for alias commands (ls for list, cd for cc etc.)
59 60 61 62 63 64 |
# File 'lib/shell.rb', line 59 def preprocess_commands(original_command) command = ALIAS_COMMANDS[original_command] # return command if alias for specific command exist in predefined ALIAS_COMMANDS # else return entered command because there is no alias for it return (command.nil? ? original_command : command) end |
#print_method_response!(response_ruby_obj) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/core.rb', line 120 def print_method_response!(response_ruby_obj) # this will raise error if found DTK::Client::ResponseErrorHandler.check(response_ruby_obj) # this will find appropriate render adapter and give output, returns boolean if print = response_ruby_obj.render_data print = [print] unless print.kind_of?(Array) print.each do |el| if el.kind_of?(String) el.each_line{|l| STDOUT << l} else PP.pp(el,STDOUT) end end end end |
#resolve_direct_access(params, config_exists = nil) ⇒ Object
check if .add_direct_access file exists, if not then add direct access and create .add_direct_access file
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/core.rb', line 156 def resolve_direct_access(params, config_exists=nil) return if params[:username_exists] puts "Processing ..." if config_exists # check to see if catalog credentials are set conn = DTK::Client::Session.get_connection response = conn.post DTK::Client::CommandBase.class, conn.rest_url("account/check_catalog_credentials"), {} # set catalog credentails if response.ok? && !response.data['catalog_credentials_set'] # setting up catalog credentials catalog_creds = DTK::Client::Configurator.ask_catalog_credentials unless catalog_creds.empty? response = conn.post DTK::Client::CommandBase.class, conn.rest_url("account/set_catalog_credentials"), { :username => catalog_creds[:username], :password => catalog_creds[:password], :validate => true} if errors = response['errors'] DTK::Client::OsUtil.print("#{errors.first['message']} You will have to set catalog credentials manually ('dtk account set-catalog-credentials').", :yellow) end end end # response = DTK::Client::Account.add_access(params[:ssh_key_path]) response, matched_pub_key, matched_username = DTK::Client::Account.add_key(params[:ssh_key_path], true, "#{DTK::Client::Session.connection_username}-client") if !response.ok? DTK::Client::OsUtil.print("We were not able to add access for current user. #{response.}. In order to properly use dtk-shell you will have to add access manually ('dtk account add-ssh-key').\n", :yellow) elsif matched_pub_key # message will be displayed by add key # TODO: Refactor this flow DTK::Client::OsUtil.print("Provided SSH PUB key has already been added.", :yellow) DTK::Client::Configurator.add_current_user_to_direct_access elsif matched_username DTK::Client::OsUtil.print("User with provided name already exists.", :yellow) else # commented out because 'add_key' method called above will also print the same message # DTK::Client::OsUtil.print("Your SSH PUB key has been successfully added.", :yellow) DTK::Client::Configurator.add_current_user_to_direct_access end response end |
#run_shell_command ⇒ Object
RUNTIME PART - STARTS HERE
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/shell.rb', line 67 def run_shell_command() # init shell client init_shell_context() # prompt init prompt = DTK::Shell::Context::DTK_ROOT_PROMPT # trap CTRL-C and remove current text without leaving the dtk-shell trap("INT"){ puts "\n" raise Interrupt } # runtime part begin while line = Readline.readline(prompt, true) prompt = execute_shell_command(line, prompt) unless line.strip.empty? end rescue DTK::Shell::ExitSignal => e # do nothing rescue ArgumentError => e puts e.backtrace if ::DTK::Configuration.get(:development_mode) retry rescue Interrupt => e retry rescue Exception => e client_internal_error = DTK::Client::DtkError::Client.label() DtkLogger.instance.error_pp("[#{client_internal_error}] #{e.}", e.backtrace) ensure puts "\n" unless e.is_a? DTK::Shell::ExitSignal # logout DTK::Client::Session.logout() # save users history DTK::Shell::Context.save_session_history(Readline::HISTORY.to_a) exit! end end |
#top_level_execute(entity_name, method_name, context_params = nil, options_args = nil, shell_execute = false) ⇒ Object
47 48 49 50 51 52 53 54 55 56 |
# File 'lib/core.rb', line 47 def top_level_execute(entity_name, method_name, context_params=nil, =nil, shell_execute=false) begin top_level_execute_core(entity_name, method_name, context_params, , shell_execute) rescue DTK::Client::DtkLoginRequiredError # re-logging user and repeating request DTK::Client::OsUtil.print("Session expired: re-establishing session & repeating given task", :yellow) DTK::Client::Session.re_initialize top_level_execute_core(entity_name, method_name, context_params, , shell_execute) end end |
#top_level_execute_core(entity_name, method_name, context_params = nil, options_args = nil, shell_execute = false) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/core.rb', line 58 def top_level_execute_core(entity_name, method_name, context_params=nil, =nil, shell_execute=false) extend DTK::Client::OsUtil entity_class = nil begin include DTK::Client::Auxiliary entity_name = entity_name.gsub("-","_") load_command(entity_name) conn = DTK::Client::Session.get_connection # if connection parameters are not set up properly then don't execute any command return if validate_connection(conn) # call proper thor class and task entity_class = DTK::Client.const_get "#{cap_form(entity_name)}" # call forwarding, in case there is no task for given entity we switch to last (n-context) and try than unless (entity_class.task_names.include?(method_name)) entity_class = DTK::Client.const_get "#{cap_form(context_params.last_entity_name.to_s)}" end response_ruby_obj = entity_class.execute_from_cli(conn,method_name,context_params,,shell_execute) # it will raise DTK::Client::Error in case of error response print_method_response!(response_ruby_obj) # process/print queued message from server DTK::Shell::MessageQueue. rescue DTK::Client::DtkLoginRequiredError => e # this error is handled in method above raise e rescue DTK::Client::DSLParsing => e DTK::Client::OsUtil.print(e., :red) rescue DTK::Client::DtkValidationError => e = e. # if !e.skip_usage_info && entity_class && method_name # usage_info = entity_class.get_usage_info(entity_name, method_name) # validation_message += ", usage: #{usage_info}" # end if e.display_usage_info && entity_class && method_name usage_info = entity_class.get_usage_info(entity_name, method_name) += ", usage: #{usage_info}" .gsub!("^^", '') if .include?("^^") .gsub!("HIDE_FROM_BASE ", '') if .include?("HIDE_FROM_BASE") end DTK::Client::OsUtil.print(, :yellow) rescue DTK::Client::DtkError => e # this are expected application errors DtkLogger.instance.error_pp(e., e.backtrace) rescue Exception => e client_internal_error = DTK::Client::DtkError::Client.label() DtkLogger.instance.fatal_pp("[#{client_internal_error}] DTK has encountered an error #{e.class}: #{e.}", e.backtrace) end end |
#validate_connection(connection) ⇒ Object
check if connection is set up properly
145 146 147 148 149 150 151 152 153 |
# File 'lib/core.rb', line 145 def validate_connection(connection) if connection.connection_error? connection.print_warning puts "\nDTK will now exit. Please set up your connection properly and try again." return true end false end |