reset lines r moves the cursor to the beginning of line ANSI escape code to clear line from cursor to end of line "e" is an alternative to "033" cf. en.wikipedia.org/wiki/ANSI_escape_code
# File lib/rhc-common.rb, line 160 def self.check_app(app) check_field(app, 'application', APP_NAME_MAX_LENGTH) end
# File lib/rhc-common.rb, line 583 def self.check_app_available(net_http, app_name, fqdn, health_check_path, result, git_url, repo_dir, no_git) # # Test several times, doubling sleep time between attempts. # sleep_time = 2 attempt = 0 puts "Confirming application '#{app_name}' is available" if @mydebug while attempt < MAX_RETRIES attempt += 1 if @mydebug puts " Attempt # #{attempt}" else print CLEAR_LINE + "Confirming application '#{app_name}' is available: Attempt # #{attempt}" end $stdout.flush url = URI.parse("http://#{fqdn}/#{health_check_path}") sleep(2.0) begin response = net_http.get_response(url) rescue Exception => e response = nil end if !response.nil? && response.code == "200" && response.body[0,1] == "1" puts CLEAR_LINE + "Confirming application '#{app_name}' is available: Success!" puts "" puts "#{app_name} published: http://#{fqdn}/" puts "git url: #{git_url}" if @mydebug unless no_git puts "To make changes to '#{app_name}', commit to #{repo_dir}/." else puts "To make changes to '#{app_name}', you must first clone it with: git clone #{git_url} " puts "Then run 'git push' to update your OpenShift Express space." end end if result && !result.empty? puts "#{result}" end return true end if !response.nil? && @mydebug puts "Server responded with #{response.code}" puts response.body unless response.code == '503' end puts " sleeping #{sleep_time} seconds" if @mydebug sleep sleep_time sleep_time = delay(sleep_time) end return false end
# File lib/rhc-common.rb, line 172 def self.check_field(field, type, max=0) if field if field =~ %r[^0-9a-zA-Z]/ puts "#{type} contains non-alphanumeric characters!" return false end if max != 0 && field.length > max puts "maximum #{type} size is #{max} characters" return false end else puts "#{type} is required" return false end true end
# File lib/rhc-common.rb, line 168 def self.check_key(keyname) check_field(keyname, 'keyname', DEFAULT_MAX_LENGTH) end
# File lib/rhc-common.rb, line 164 def self.check_namespace(namespace) check_field(namespace, 'namespace', DEFAULT_MAX_LENGTH) end
Invalid chars (") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) () (*) (=) (~)
# File lib/rhc-common.rb, line 147 def self.check_rhlogin(rhlogin) if rhlogin if rhlogin =~ %r["\$\^<>\|%\/;:,\\\*=~]/ puts 'RHLogin may not contain any of these characters: (\") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)' return false end else puts "RHLogin is required" return false end true end
# File lib/rhc-common.rb, line 89 def self.check_version if @@api_version =~ PATTERN_VERSION if API != @@api_version puts "\nNOTICE: Client API version (#{API}) does not match the server (#{@@api_version}).\nThough requests may succeed, you should consider updating your client tools.\n\n" end end end
# File lib/rhc-common.rb, line 412 def self.create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, is_embedded_jenkins=false) puts "Creating application: #{app_name}" data = {:cartridge => app_type, :action => 'configure', :app_name => app_name, :rhlogin => rhlogin } if @mydebug data[:debug] = true end json_data = generate_json(data) url = URI.parse("https://#{libra_server}/broker/cartridge") response = http_post(net_http, url, json_data, password) if response.code == '200' json_resp = JSON.parse(response.body) print_response_success(json_resp) json_data = JSON.parse(json_resp['data']) health_check_path = json_data['health_check_path'] app_uuid = json_data['uuid'] result = json_resp['result'] puts "DEBUG: '#{app_name}' creation returned success." if @mydebug else print_response_err(response) end # # At this point, we need to register a handler to guarantee app # cleanup on any exceptions or calls to exit # at_exit do unless $!.nil? || $!.is_a?(SystemExit) && $!.success? puts "Cleaning up application" destroy_app(libra_server, net_http, app_name, rhlogin, password) end end namespace = user_info['user_info']['namespace'] rhc_domain = user_info['user_info']['rhc_domain'] fqdn = "#{app_name}-#{namespace}.#{rhc_domain}" loop = 0 # # Confirm that the host exists in DNS # unless no_dns puts "Now your new domain name is being propagated worldwide (this might take a minute)..." # Allow DNS to propogate sleep 15 # Now start checking for DNS sleep_time = 2 while loop < MAX_RETRIES && !hostexist?(fqdn) sleep sleep_time loop+=1 print CLEAR_LINE + " retry # #{loop} - Waiting for DNS: #{fqdn}" $stdout.flush sleep_time = delay(sleep_time) end end # if we have executed print statements, then move to the next line if loop > 0 puts end # construct the Git URL git_url = "ssh://#{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain}/~/git/#{app_name}.git/" # If the hostname couldn't be resolved, print out the git URL # and exit cleanly. This will help solve issues where DNS times # out in APAC, etc on resolution. if loop >= MAX_RETRIES puts " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING: We weren't able to lookup your hostname (#{fqdn}) in a reasonable amount of time. This can happen periodically and will just take an extra minute or two to propagate depending on where you are in the world. Once you are able to access your application in a browser, you can then clone your git repository. Application URL: http://#{fqdn} Git Repository URL: #{git_url} Git Clone command: git clone #{git_url} #{repo_dir} If you can't get your application '#{app_name}' running in the browser, you can also try destroying and recreating the application as well using: rhc-ctl-app -c destroy -a #{app_name} -l #{rhlogin} If this doesn't work for you, let us know in the forums or in IRC and we'll make sure to get you up and running. Forums: https://www.redhat.com/openshift/forums/express IRC: #openshift (on Freenode) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " exit 0 end # # Pull new repo locally # unless no_git puts "Pulling new repo down" if @mydebug puts "git clone --quiet #{git_url} #{repo_dir}" if @mydebug quiet = (@mydebug ? ' ' : '--quiet ') git_clone = %x<git clone #{quiet} #{git_url} #{repo_dir}> if $?.exitstatus != 0 puts "Error in git clone" puts git_clone exit 216 end else if is_embedded_jenkins # if this is a jenkins client application to be embedded, # then print this message only in debug mode if @mydebug puts " Note: There is a git repo for your Jenkins application '#{app_name}' but it isn't being downloaded as part of this process. In most cases it isn't needed but you can always clone it later. " end else puts " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT: Since the -n flag was specified, no local repo has been created. This means you can't make changes to your published application until after you clone the repo yourself. See the git url below for more information. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " end end # # At this point, we need to register a handler to guarantee git # repo cleanup on any exceptions or calls to exit # unless no_git at_exit do unless $!.nil? || $!.is_a?(SystemExit) && $!.success? puts "Cleaning up git repo" FileUtils.rm_rf repo_dir end end end return {:app_name => app_name, :fqdn => fqdn, :health_check_path => health_check_path, :git_url => git_url, :repo_dir => repo_dir, :result => result } end
# File lib/rhc-common.rb, line 706 def self.ctl_app(libra_server, net_http, app_name, rhlogin, password, action, embedded=false, framework=nil, server_alias=nil, print_result=true) data = {:action => action, :app_name => app_name, :rhlogin => rhlogin } data[:server_alias] = server_alias if server_alias if framework data[:cartridge] = framework end if @mydebug data[:debug] = true end json_data = generate_json(data) url = nil if embedded url = URI.parse("https://#{libra_server}/broker/embed_cartridge") else url = URI.parse("https://#{libra_server}/broker/cartridge") end response = http_post(net_http, url, json_data, password) if response.code == '200' json_resp = JSON.parse(response.body) print_response_success(json_resp, print_result || @mydebug) else print_response_err(response) end end
# File lib/rhc-common.rb, line 76 def self.debug(bool) @mydebug = bool end
# File lib/rhc-common.rb, line 97 def self.delay(time, adj=DEFAULT_DELAY) (time*=adj).to_int end
# File lib/rhc-common.rb, line 640 def self.destroy_app(libra_server, net_http, app_name, rhlogin, password) json_data = generate_json( {:action => 'deconfigure', :app_name => app_name, :rhlogin => rhlogin }) url = URI.parse("https://#{libra_server}/broker/cartridge") http_post(net_http, url, json_data, password) end
# File lib/rhc-common.rb, line 101 def self.generate_json(data) data['api'] = API json = JSON.generate(data) json end
# File lib/rhc-common.rb, line 140 def self.get_cartridge_listing(carts, sep, libra_server, net_http, cart_type="standalone", print_result=nil) carts = get_cartridges_list(libra_server, net_http, cart_type, print_result) if carts.nil? carts.join(sep) end
# File lib/rhc-common.rb, line 107 def self.get_cartridges_list(libra_server, net_http, cart_type="standalone", print_result=nil) puts "Obtaining list of cartridges (please excuse the delay)..." data = {'cart_type' => cart_type} if @mydebug data[:debug] = true end print_post_data(data) json_data = generate_json(data) url = URI.parse("https://#{libra_server}/broker/cartlist") response = http_post(net_http, url, json_data, "none") unless response.code == '200' print_response_err(response) return [] end begin json_resp = JSON.parse(response.body) rescue JSON::ParserError exit 1 end update_server_api_v(json_resp) if print_result print_response_success(json_resp) end begin carts = (JSON.parse(json_resp['data']))['carts'] rescue JSON::ParserError exit 1 end carts end
# File lib/rhc-common.rb, line 284 def self.get_password password = nil begin print "Password: " system "stty -echo" password = gets.chomp rescue Interrupt puts "\n" exit 1 ensure system "stty echo" end puts "\n" password end
# File lib/rhc-common.rb, line 250 def self.get_ssh_keys(libra_server, rhlogin, password, net_http) data = {'rhlogin' => rhlogin, 'action' => 'list-keys'} if @mydebug data[:debug] = true end print_post_data(data) json_data = generate_json(data) url = URI.parse("https://#{libra_server}/broker/ssh_keys") response = http_post(net_http, url, json_data, password) unless response.code == '200' if response.code == '401' puts "Invalid user credentials" exit 97 else print_response_err(response) end exit 1 end begin json_resp = JSON.parse(response.body) rescue JSON::ParserError exit 1 end update_server_api_v(json_resp) begin ssh_keys = (JSON.parse(json_resp['data'].to_s))['keys'] rescue JSON::ParserError exit 1 end ssh_keys end
# File lib/rhc-common.rb, line 206 def self.get_user_info(libra_server, rhlogin, password, net_http, print_result, not_found_message=nil) data = {'rhlogin' => rhlogin} if @mydebug data[:debug] = true end print_post_data(data) json_data = generate_json(data) url = URI.parse("https://#{libra_server}/broker/userinfo") response = http_post(net_http, url, json_data, password) unless response.code == '200' if response.code == '404' if not_found_message puts not_found_message else puts "A user with rhlogin '#{rhlogin}' does not have a registered domain. Be sure to run rhc-create-domain before using the other rhc tools." end exit 99 elsif response.code == '401' puts "Invalid user credentials" exit 97 else print_response_err(response) end exit 1 end begin json_resp = JSON.parse(response.body) rescue JSON::ParserError exit 1 end update_server_api_v(json_resp) if print_result print_response_success(json_resp) end begin user_info = JSON.parse(json_resp['data'].to_s) rescue JSON::ParserError exit 1 end user_info end
Check if host exists
# File lib/rhc-common.rb, line 406 def self.hostexist?(host) dns = Resolv::DNS.new resp = dns.getresources(host, Resolv::DNS::Resource::IN::A) return resp.any? end
# File lib/rhc-common.rb, line 300 def self.http_post(http, url, json_data, password) req = http::Post.new(url.path) puts "Contacting #{url.scheme}://#{url.host}" if @mydebug req.set_form_data({'json_data' => json_data, 'password' => password}) http = http.new(url.host, url.port) http.open_timeout = @mytimeout if url.scheme == "https" http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE end begin response = http.start {|http| http.request(req)} if response.code == '404' && response.content_type == 'text/html' # TODO probably want to remove this at some point puts "!!!! WARNING !!!! WARNING !!!! WARNING !!!!" puts "RHCloud server not found. You might want to try updating your rhc client tools." exit 218 end response rescue Exception => e puts "There was a problem communicating with the server. Response message: #{e.message}" puts "If you were disconnected it is possible the operation finished without being able to report success." puts "You can use rhc-user-info and rhc-ctl-app to learn about the status of your user and application(s)." exit 219 end end
Runs rhc-list-ports on server to check available ports :stderr return user-friendly port name, :stdout returns 127.0.0.1:8080 format
# File lib/rhc-common.rb, line 652 def self.list_ports(rhc_domain, namespace, app_name, app_uuid, debug=true) ip_and_port_simple_regex = %r[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:[0-9]{1,5}/ ssh_host = "#{app_name}-#{namespace}.#{rhc_domain}" ssh_cmd = "ssh -t #{app_uuid}@#{ssh_host} 'rhc-list-ports'" hosts_and_ports = [] hosts_and_ports_descriptions = [] puts ssh_cmd if debug Open3.popen3(ssh_cmd) { |stdin, stdout, stderr| stdout.each { |line| line = line.chomp if ip_and_port_simple_regex.match(line) hosts_and_ports << line end } stderr.each { |line| line = line.chomp if line.index(ip_and_port_simple_regex) hosts_and_ports_descriptions << line end } } #hosts_and_ports_descriptions = stderr.gets.chomp.split(/\n/) #hosts_and_ports = stdout.gets.chomp.split(/\n/) # Net::SSH.start(ssh_host, app_uuid) do |ssh| # ssh.exec!("rhc-list-ports") do |channel, stream, data| # array = data.split(/\n/) # if stream == :stderr # hosts_and_ports_descriptions = array # elsif stream == :stdout # hosts_and_ports = array # end # end # end return hosts_and_ports, hosts_and_ports_descriptions end
# File lib/rhc-common.rb, line 369 def self.print_json_body(json_resp, print_result=true) print_response_messages(json_resp) exit_code = json_resp['exit_code'] if @mydebug if json_resp['debug'] puts '' puts 'DEBUG:' puts json_resp['debug'] puts '' puts "Exit Code: #{exit_code}" if (json_resp.length > 3) json_resp.each do |k,v| if !DEBUG_INGORE_KEYS.has_key?(k) puts "#{k.to_s}: #{v.to_s}" end end end end if json_resp['api'] puts "API version: #{json_resp['api']}" end if json_resp['broker'] puts "Broker version: #{json_resp['broker']}" end end if print_result && json_resp['result'] puts '' puts 'RESULT:' puts json_resp['result'] puts '' end exit_code end
# File lib/rhc-common.rb, line 189 def self.print_post_data(h) if (@mydebug) puts 'Submitting form:' h.each do |k,v| if k.to_s != 'password' puts "#{k.to_s}: #{v.to_s}" else print 'password: ' for i in (1..v.length) print 'X' end puts '' end end end end
# File lib/rhc-common.rb, line 328 def self.print_response_err(response) puts "Problem reported from server. Response code was #{response.code}." if (!@mydebug) puts "Re-run with -d for more information." end exit_code = 1 if response.content_type == 'application/json' begin json_resp = JSON.parse(response.body) exit_code = print_json_body(json_resp) rescue JSON::ParserError exit_code = 1 end elsif @mydebug puts "HTTP response from server is #{response.body}" end exit exit_code.nil? ? 666 : exit_code end
# File lib/rhc-common.rb, line 347 def self.print_response_messages(json_resp) messages = json_resp['messages'] if (messages && !messages.empty?) puts '' puts 'MESSAGES:' puts messages puts '' end end
# File lib/rhc-common.rb, line 357 def self.print_response_success(json_resp, print_result=false) if @mydebug print "Response from server:" $stdout.flush print_json_body(json_resp, print_result) elsif print_result print_json_body(json_resp) else print_response_messages(json_resp) end end
# File lib/rhc-common.rb, line 66 def self.timeout(val) if val @mytimeout = val.to_i unless @mytimeout > 0 puts 'Timeout must be specified as a number greater than 0' exit 1 end end end
# File lib/rhc-common.rb, line 80 def self.update_server_api_v(dict) if !dict['broker'].nil? && (dict['broker'] =~ PATTERN_VERSION) @@broker_version = dict['broker'] end if !dict['api'].nil? && (dict['api'] =~ PATTERN_VERSION) @@api_version = dict['api'] end end