rhc 0.92.11 → 0.93.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/README.md +1 -9
  2. data/Rakefile +1 -55
  3. data/bin/rhc +31 -1
  4. data/bin/rhc-app +62 -127
  5. data/bin/rhc-chk +6 -7
  6. data/bin/rhc-create-app +8 -8
  7. data/bin/rhc-create-domain +6 -86
  8. data/bin/rhc-ctl-app +3 -3
  9. data/bin/rhc-ctl-domain +4 -4
  10. data/bin/rhc-domain +16 -18
  11. data/bin/rhc-domain-info +3 -3
  12. data/bin/rhc-port-forward +127 -24
  13. data/bin/rhc-snapshot +7 -46
  14. data/bin/rhc-sshkey +13 -79
  15. data/bin/rhc-tail-files +16 -8
  16. data/lib/rhc-common.rb +406 -230
  17. data/lib/rhc-rest.rb +3 -3
  18. data/lib/rhc-rest/client.rb +1 -1
  19. data/lib/rhc-rest/domain.rb +1 -1
  20. data/lib/rhc.rb +20 -0
  21. data/lib/rhc/cli.rb +38 -0
  22. data/lib/rhc/client.rb +15 -0
  23. data/lib/rhc/commands.rb +32 -0
  24. data/lib/rhc/commands/base.rb +67 -0
  25. data/lib/rhc/commands/server.rb +24 -0
  26. data/lib/rhc/config.rb +141 -0
  27. data/lib/rhc/core_ext.rb +15 -0
  28. data/lib/rhc/helpers.rb +142 -0
  29. data/lib/rhc/json.rb +52 -0
  30. data/lib/rhc/targz.rb +46 -0
  31. data/lib/rhc/vendor/okjson.rb +600 -0
  32. data/lib/rhc/vendor/zliby.rb +628 -0
  33. data/lib/rhc/wizard.rb +579 -0
  34. data/spec/rhc/assets/foo.txt +1 -0
  35. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  36. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  37. data/spec/rhc/cli_spec.rb +24 -0
  38. data/spec/rhc/command_spec.rb +88 -0
  39. data/spec/rhc/commands/server_spec.rb +39 -0
  40. data/spec/rhc/helpers_spec.rb +171 -0
  41. data/spec/rhc/json_spec.rb +30 -0
  42. data/spec/rhc/targz_spec.rb +42 -0
  43. data/spec/rhc/wizard_spec.rb +426 -0
  44. data/spec/spec_helper.rb +192 -0
  45. data/test/functional/application_test.rb +71 -0
  46. data/test/functional/domain_test.rb +123 -0
  47. data/test/functional/test_credentials.rb +5 -0
  48. data/test/sample-usage.rb +122 -0
  49. data/test/support/server.rb +14 -0
  50. data/test/support/testcase.rb +3 -0
  51. data/test/test_helper.rb +4 -0
  52. data/test/unit/command_test.rb +19 -0
  53. metadata +181 -29
  54. data/ext/mkrf_conf.rb +0 -58
  55. data/lib/rhc +0 -115
data/lib/rhc-rest.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'rest-client'
3
3
  require 'logger'
4
- require 'json'
5
4
  require 'rhc-rest/exceptions/exceptions'
6
5
  require 'rhc-rest/application'
7
6
  require 'rhc-rest/cartridge'
@@ -9,6 +8,7 @@ require 'rhc-rest/client'
9
8
  require 'rhc-rest/domain'
10
9
  require 'rhc-rest/key'
11
10
  require 'rhc-rest/user'
11
+ require 'rhc/helpers'
12
12
 
13
13
  @@end_point = ""
14
14
  @@headers = {:accept => :json}
@@ -24,7 +24,7 @@ module Rhc
24
24
  end
25
25
 
26
26
  def parse_response(response)
27
- result = JSON.parse(response)
27
+ result = RHC::Json.decode(response)
28
28
  type = result['type']
29
29
  data = result['data']
30
30
  case type
@@ -92,7 +92,7 @@ module Rhc
92
92
  def process_error_response(response)
93
93
  messages = Array.new
94
94
  begin
95
- result = JSON.parse(response)
95
+ result = RHC::Json.decode(response)
96
96
  messages = result['messages']
97
97
  rescue Exception => e
98
98
  logger.debug "Response did not include a message from server" if @mydebug
@@ -13,7 +13,7 @@ module Rhc
13
13
  request = RestClient::Request.new(:url => end_point, :method => :get, :headers => @@headers)
14
14
  begin
15
15
  response = request.execute
16
- result = JSON.parse(response)
16
+ result = RHC::Json.decode(response)
17
17
  @links = send(request)
18
18
  rescue RestClient::ExceptionWithResponse => e
19
19
  logger.error "Failed to get API #{e.response}"
@@ -24,7 +24,7 @@ module Rhc
24
24
  end
25
25
  timeout = nil
26
26
  if options[:scale]
27
- timeout = 180 # 3 minute timeout for scalable app
27
+ timeout = 300 # 5 minute timeout for scalable app
28
28
  end
29
29
  request = RestClient::Request.new(:url => url, :method => method, :headers => @@headers, :payload => payload, :timeout => timeout)
30
30
  return send(request)
data/lib/rhc.rb ADDED
@@ -0,0 +1,20 @@
1
+ # require 'rhc/version' #FIXME gem should know version
2
+ # FIXME Remove rubygems from requirements, ensure library is correct
3
+
4
+ # Only require external gem dependencies here
5
+ require 'rest_client'
6
+ require 'logger'
7
+
8
+ # Extend core methods
9
+ require 'rhc/core_ext'
10
+
11
+ module RHC
12
+ module Commands; end
13
+
14
+ autoload :Helpers, 'rhc/helpers'
15
+ end
16
+
17
+ # Replace me with proper autoloads on the module RHC
18
+ require 'rhc-common'
19
+ require 'rhc-rest'
20
+
data/lib/rhc/cli.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'rhc'
2
+ require 'commander'
3
+ require 'commander/runner'
4
+ require 'commander/delegates'
5
+ require 'rhc/commands'
6
+
7
+ include Commander::UI
8
+ include Commander::UI::AskForClass
9
+
10
+ module RHC
11
+ #
12
+ # Run and execute a command line session with the RHC tools.
13
+ #
14
+ # You can invoke the CLI with:
15
+ # bundle exec ruby -e 'require "rhc/cli"; RHC::CLI.start(ARGV);' -- <arguments>
16
+ #
17
+ # from the gem directory.
18
+ #
19
+ module CLI
20
+
21
+ extend Commander::Delegates
22
+
23
+ def self.set_terminal
24
+ $terminal.wrap_at = HighLine::SystemExtensions.terminal_size.first - 5 rescue 80 if $stdin.tty?
25
+ end
26
+
27
+ def self.start(args)
28
+ Commander::Runner.instance_variable_set :@singleton, Commander::Runner.new(args)
29
+
30
+ program :name, 'rhc'
31
+ program :version, '0.0.0' #FIXME pull from versions.rb
32
+ program :description, 'Command line interface for OpenShift.'
33
+
34
+ RHC::Commands.load.to_commander
35
+ exit(run! || 0)
36
+ end
37
+ end
38
+ end
data/lib/rhc/client.rb ADDED
@@ -0,0 +1,15 @@
1
+ class RHC::Client
2
+ def initialize() #auth info
3
+ end
4
+
5
+ include RHC::Helpers
6
+
7
+ def get(uri, headers={})
8
+ # absolute uris are called directly, relative uris are called with
9
+ # the rest api root, and server relative uris are called against the
10
+ # host. Allow simple templatization via t()
11
+ end
12
+ def t(uri, opts)
13
+ # templatize uri using AddressableTemplate and opts
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ require 'rhc/config'
2
+
3
+ module RHC
4
+ module Commands
5
+ def self.load
6
+ Dir[File.join(File.dirname(__FILE__), "commands", "*.rb")].each do |file|
7
+ require file
8
+ end
9
+ self
10
+ end
11
+ def self.add(opts)
12
+ commands[opts[:name]] = opts
13
+ end
14
+ def self.to_commander(instance=Commander::Runner.instance)
15
+ commands.each_pair do |name, opts|
16
+ instance.command name do |c|
17
+ c.option '--config PATH', String, 'Path of alternate config'
18
+ c.when_called do |args, options|
19
+ RHC::Config.set_opts_config(options.config) if options.config
20
+ opts[:class].new(args, options).send(opts[:method])
21
+ end
22
+ end
23
+ end
24
+ self
25
+ end
26
+
27
+ protected
28
+ def self.commands
29
+ @commands ||= {}
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,67 @@
1
+ require 'commander'
2
+ require 'commander/delegates'
3
+ require 'rhc/helpers'
4
+
5
+ class RHC::Commands::Base
6
+
7
+ attr_reader :args, :options
8
+
9
+ def initialize(args=[], options={})
10
+ @args, @options = args, options
11
+ end
12
+
13
+ protected
14
+ include RHC::Helpers
15
+
16
+ def application
17
+ #@application ||= ... identify current application or throw,
18
+ # indicating one is needed. Should check
19
+ # options (commands which have it as an ARG
20
+ # should set it onto options), then check
21
+ # current git repo for remote, fail.
22
+ end
23
+
24
+ def client
25
+ #@client ||= ... Return a client object capable of making calls
26
+ # to the OpenShift API that transforms intent
27
+ # and options, to remote calls, and then handle
28
+ # the output (or failures) into exceptions and
29
+ # formatted object output. Most interactions
30
+ # should be through this call pattern.
31
+ #
32
+ # Initialize with auth (a separate responsibility
33
+ # object).
34
+ end
35
+
36
+ class InvalidCommand < StandardError ; end
37
+
38
+ def self.inherited(klass)
39
+ unless klass == RHC::Commands::Base
40
+ end
41
+ end
42
+
43
+ def self.method_added(method)
44
+ return if self == RHC::Commands::Base
45
+ return if private_method_defined? method
46
+ return if protected_method_defined? method
47
+
48
+ method_name = method.to_s == 'run' ? nil : method.to_s
49
+ name = [method_name]
50
+ name.unshift(self.object_name).compact!
51
+ raise InvalidCommand, "Either object_name must be set or a non default method defined" if name.empty?
52
+ RHC::Commands.add({
53
+ :name => name.join(' '),
54
+ :class => self,
55
+ :method => method,
56
+ });
57
+ end
58
+
59
+ def self.object_name(value=nil)
60
+ @object_name ||= begin
61
+ value ||= if self.name && !self.name.empty?
62
+ self.name.split('::').last
63
+ end
64
+ value.to_s.downcase if value
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,24 @@
1
+ require 'rhc/commands/base'
2
+
3
+ module RHC::Commands
4
+ class Server < Base
5
+ def run
6
+ status = decode_json(RestClient.get("https://#{openshift_server}/app/status/status.json").body)
7
+ open = status['open']
8
+
9
+ (success 'All systems running fine' and return 0) if open.blank?
10
+
11
+ open.each do |i|
12
+ i = i['issue']
13
+ say color("%-3s %s" % ["##{i['id']}", i['title']], :bold)
14
+ items = i['updates'].map{ |u| [u['description'], date(u['created_at'])] }
15
+ items.unshift ['Opened', date(i['created_at'])]
16
+ table(items, :align => [nil,:right], :join => ' ').each{ |s| say " #{s}" }
17
+ end
18
+ say "\n"
19
+ warn pluralize(open.length, "open issue")
20
+
21
+ open.length #exit with the count of open items
22
+ end
23
+ end
24
+ end
data/lib/rhc/config.rb ADDED
@@ -0,0 +1,141 @@
1
+ require 'parseconfig'
2
+
3
+ module RHC
4
+ module Config
5
+ def self.initialize
6
+ @@defaults = ParseConfig.new()
7
+ @@global_config = nil
8
+ @@local_config = nil
9
+ @@opts_config = nil
10
+ @@default_proxy = nil
11
+ @@env_config = ParseConfig.new()
12
+
13
+ @@defaults.add('libra_server', 'openshift.redhat.com')
14
+ @@env_config.add('libra_server', ENV['LIBRA_SERVER']) if ENV['LIBRA_SERVER']
15
+
16
+ #
17
+ # Config paths... /etc/openshift/express.conf or $GEM/conf/express.conf -> ~/.openshift/express.conf
18
+ #
19
+
20
+ @@conf_name = 'express.conf'
21
+ _linux_cfg = '/etc/openshift/' + @@conf_name
22
+ _gem_cfg = File.join(File.expand_path(File.dirname(__FILE__) + "/../../conf"), @@conf_name)
23
+
24
+ config_path = File.exists?(_linux_cfg) ? _linux_cfg : _gem_cfg
25
+ @@home_dir = File.expand_path("~")
26
+ @@home_conf_path = File.join(@@home_dir, '.openshift')
27
+ @@local_config_path = File.join(@@home_conf_path, @@conf_name)
28
+
29
+ begin
30
+ @@global_config = ParseConfig.new(config_path)
31
+ @@local_config = ParseConfig.new(File.expand_path(@@local_config_path)) if File.exists?(@@local_config_path)
32
+ rescue Errno::EACCES => e
33
+ puts "Could not open config file: #{e.message}"
34
+ exit 253
35
+ end
36
+ end
37
+
38
+ self.initialize
39
+
40
+ # used for tests
41
+ def self.home_dir=(home_dir)
42
+ @@home_dir=home_dir
43
+ @@home_conf_path = File.join(@@home_dir, '.openshift')
44
+ @@local_config_path = File.join(@@home_conf_path, @@conf_name)
45
+ end
46
+
47
+ def self.get_value(key)
48
+ # evaluate in cascading order
49
+ configs = [@@opts_config, @@env_config, @@local_config, @@global_config, @@defaults]
50
+ result = nil
51
+ configs.each do |conf|
52
+ result = conf.get_value(key) if !conf.nil?
53
+ break if !result.nil?
54
+ end
55
+
56
+ result
57
+ end
58
+
59
+ # Public: configures the default user for this session
60
+ def self.config_user(username)
61
+ @@defaults.add('default_rhlogin', username)
62
+ end
63
+
64
+ def self.set_local_config(confpath)
65
+ begin
66
+ @@local_config = ParseConfig.new(File.expand_path(confpath))
67
+ rescue Errno::EACCES => e
68
+ puts "Could not open config file: #{e.message}"
69
+ exit 253
70
+ end
71
+ end
72
+
73
+ def self.set_opts_config(confpath)
74
+ begin
75
+ @@opts_config = ParseConfig.new(File.expand_path(confpath))
76
+ rescue Errno::EACCES => e
77
+ puts "Could not open config file: #{e.message}"
78
+ exit 253
79
+ end
80
+ end
81
+
82
+ def self.check_cpath(opts)
83
+ unless opts["config"].nil?
84
+ opts_config_path = File.expand_path(opts["config"])
85
+ if !File.readable?(opts_config_path)
86
+ puts "Could not open config file: #{@opts_config_path}"
87
+ exit 253
88
+ else
89
+ set_opts_config(opts_config_path)
90
+ end
91
+ end
92
+ end
93
+
94
+ def self.has_global_config?
95
+ !@@global_config.nil?
96
+ end
97
+
98
+ def self.has_local_config?
99
+ !@@local_config.nil?
100
+ end
101
+
102
+ def self.has_opts_config?
103
+ !@@opts_config.nil?
104
+ end
105
+
106
+ # Public: convinience function to see if we should run the wizard
107
+ def self.should_run_wizard?
108
+ not (has_local_config? or has_opts_config?)
109
+ end
110
+
111
+ def self.local_config_path
112
+ @@local_config_path
113
+ end
114
+
115
+ def self.home_conf_path
116
+ @@home_conf_path
117
+ end
118
+
119
+ def self.home_dir
120
+ @@home_dir
121
+ end
122
+
123
+ def self.default_proxy
124
+ #
125
+ # Check for proxy environment
126
+ #
127
+ if @@default_proxy.nil?
128
+ if ENV['http_proxy']
129
+ if ENV['http_proxy']!~/^(\w+):\/\// then
130
+ ENV['http_proxy']="http://" + ENV['http_proxy']
131
+ end
132
+ proxy_uri=URI.parse(ENV['http_proxy'])
133
+ @@default_proxy = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
134
+ else
135
+ @@default_proxy = Net::HTTP
136
+ end
137
+ end
138
+ @@default_proxy
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,15 @@
1
+ # From Rails core_ext/object.rb
2
+ require 'rhc/json'
3
+
4
+ class Object
5
+ def present?
6
+ !blank?
7
+ end
8
+ def blank?
9
+ respond_to?(:empty?) ? empty? : !self
10
+ end
11
+
12
+ def to_json
13
+ RHC::Json.encode(self)
14
+ end
15
+ end
@@ -0,0 +1,142 @@
1
+ require 'commander/user_interaction'
2
+ require 'rhc/config'
3
+
4
+ module RHC
5
+ module Helpers
6
+
7
+ # helpers always have Commander UI available
8
+ include Commander::UI
9
+ include Commander::UI::AskForClass
10
+
11
+ extend self
12
+
13
+ def decode_json(s)
14
+ RHC::Vendor::OkJson.decode(s)
15
+ end
16
+
17
+ def date(s)
18
+ now = Time.now
19
+ d = datetime_rfc3339(s)
20
+ if now.year == d.year
21
+ return d.strftime('%l:%M %p').strip if now.yday == d.yday
22
+ end
23
+ d.strftime('%b %d %l:%M %p')
24
+ end
25
+
26
+ def datetime_rfc3339(s)
27
+ DateTime.strptime(s, '%Y-%m-%dT%H:%M:%S%z')
28
+ # Replace with d = DateTime.rfc3339(s)
29
+ end
30
+
31
+ def openshift_server
32
+ RHC::Config.get_value('libra_server')
33
+ end
34
+
35
+ def success(*args)
36
+ args.each{ |a| say color(a, :green) }
37
+ end
38
+ def warn(*args)
39
+ args.each{ |a| say color(a, :yellow) }
40
+ end
41
+
42
+ def color(s, color)
43
+ $terminal.color(s, color)
44
+ end
45
+
46
+ def pluralize(count, s)
47
+ count == 1 ? "#{count} #{s}" : "#{count} #{s}s"
48
+ end
49
+
50
+ def table(items, opts={}, &block)
51
+ items = items.map &block if block_given?
52
+ columns = []
53
+ max = items.each do |item|
54
+ item.each_with_index do |s, i|
55
+ item[i] = s.to_s
56
+ columns[i] = [columns[i] || 0, s.length].max if s.respond_to?(:length)
57
+ end
58
+ end
59
+ align = opts[:align] || []
60
+ join = opts[:join] || ' '
61
+ items.map do |item|
62
+ item.each_with_index.map{ |s,i| s.send((align[i] == :right ? :rjust : :ljust), columns[i], ' ') }.join(join).strip
63
+ end
64
+ end
65
+
66
+ ##
67
+ # section
68
+ #
69
+ # highline helper mixin which correctly formats block of say and ask
70
+ # output to have correct margins. section remembers the last margin
71
+ # used and calculates the relitive margin from the previous section.
72
+ # For example:
73
+ #
74
+ # section(bottom=1) do
75
+ # say "Hello"
76
+ # end
77
+ #
78
+ # section(top=1) do
79
+ # say "World"
80
+ # end
81
+ #
82
+ # Will output:
83
+ #
84
+ # > Hello
85
+ # >
86
+ # > World
87
+ #
88
+ # with only one newline between the two. Biggest margin wins.
89
+ #
90
+ # params:
91
+ # top - top margin specified in lines
92
+ # bottom - bottom margin specified in line
93
+ #
94
+ @@section_bottom_last = 0
95
+ def section(params={}, &block)
96
+ top = params[:top]
97
+ top = 0 if top.nil?
98
+ bottom = params[:bottom]
99
+ bottom = 0 if bottom.nil?
100
+
101
+ # add more newlines if top is greater than the last section's bottom margin
102
+ top_margin = @@section_bottom_last
103
+
104
+ # negitive previous bottoms indicate that an untracked newline was
105
+ # printed and so we do our best to negate it since we can't remove it
106
+ if top_margin < 0
107
+ top += top_margin
108
+ top_margin = 0
109
+ end
110
+
111
+ until top_margin >= top
112
+ say "\n"
113
+ top_margin += 1
114
+ end
115
+
116
+ block.call
117
+
118
+ bottom_margin = 0
119
+ until bottom_margin >= bottom
120
+ say "\n"
121
+ bottom_margin += 1
122
+ end
123
+
124
+ @@section_bottom_last = bottom
125
+ end
126
+
127
+ ##
128
+ # paragraph
129
+ #
130
+ # highline helper which creates a section with margins of 1, 1
131
+ #
132
+ def paragraph(&block)
133
+ section(:top => 1, :bottom => 1, &block)
134
+ end
135
+
136
+ # Platform helpers
137
+ def jruby? ; RUBY_PLATFORM =~ /java/i end
138
+ def windows? ; RUBY_PLATFORM =~ /win(32|dows|ce)|djgpp|(ms|cyg|bcc)win|mingw32/i end
139
+ def unix? ; !jruby? && !windows? end
140
+
141
+ end
142
+ end