rhc 1.1.11 → 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/features/cartridge.feature +14 -1
  2. data/features/domain.feature +1 -1
  3. data/features/lib/rhc_helper.rb +3 -3
  4. data/features/lib/rhc_helper/app.rb +11 -3
  5. data/features/lib/rhc_helper/cartridge.rb +8 -0
  6. data/features/lib/rhc_helper/domain.rb +8 -15
  7. data/features/lib/rhc_helper/httpify.rb +11 -6
  8. data/features/lib/rhc_helper/runnable.rb +43 -7
  9. data/features/sshkey.feature +3 -4
  10. data/features/step_definitions/application_steps.rb +5 -5
  11. data/features/step_definitions/cartridge_steps.rb +12 -0
  12. data/features/step_definitions/client_steps.rb +3 -2
  13. data/features/step_definitions/sshkey_steps.rb +3 -3
  14. data/features/support/assumptions.rb +11 -11
  15. data/features/support/before_hooks.rb +23 -5
  16. data/features/support/env.rb +14 -4
  17. data/lib/rhc-common.rb +5 -2
  18. data/lib/rhc/cartridge_helpers.rb +7 -1
  19. data/lib/rhc/command_runner.rb +8 -4
  20. data/lib/rhc/commands.rb +6 -0
  21. data/lib/rhc/commands/app.rb +15 -7
  22. data/lib/rhc/commands/base.rb +3 -3
  23. data/lib/rhc/commands/cartridge.rb +78 -2
  24. data/lib/rhc/commands/port-forward.rb +137 -24
  25. data/lib/rhc/exceptions.rb +23 -8
  26. data/lib/rhc/helpers.rb +25 -4
  27. data/lib/rhc/output_helpers.rb +23 -0
  28. data/lib/rhc/rest.rb +38 -19
  29. data/lib/rhc/rest/base.rb +7 -3
  30. data/lib/rhc/rest/cartridge.rb +10 -1
  31. data/lib/rhc/usage_templates/command_help.erb +12 -12
  32. data/lib/rhc/usage_templates/command_syntax_help.erb +1 -1
  33. data/lib/rhc/usage_templates/help.erb +3 -3
  34. data/lib/rhc/usage_templates/missing_help.erb +1 -1
  35. data/lib/rhc/version.rb +1 -5
  36. data/lib/rhc/wizard.rb +4 -32
  37. data/spec/rest_spec_helper.rb +18 -4
  38. data/spec/rhc/commands/cartridge_spec.rb +91 -0
  39. data/spec/rhc/commands/domain_spec.rb +6 -2
  40. data/spec/rhc/commands/port-forward_spec.rb +95 -54
  41. data/spec/rhc/commands/snapshot_spec.rb +5 -0
  42. data/spec/rhc/rest_spec.rb +23 -2
  43. data/spec/rhc/wizard_spec.rb +9 -12
  44. data/spec/spec_helper.rb +5 -0
  45. metadata +228 -224
@@ -1,4 +1,4 @@
1
- @single_cartridge @domain_required
1
+ @single_cartridge @domain_required @cartridge_storage_user_required
2
2
  Feature: Single Cartridge Tests
3
3
 
4
4
  # Need to keep these outlines duplicated until we update cucumber to allow tagged examples
@@ -32,3 +32,16 @@ Feature: Single Cartridge Tests
32
32
  | php-5.3 | PHP 5.3 |
33
33
  | mongodb-2.2 | MongoDB NoSQL |
34
34
  | cron-1.4 | Cron 1.4 |
35
+
36
+ # Commenting this out for US2438
37
+ # Scenario Outline: Cartridge Storage
38
+ # Given we have a running mysql-5.1 cartridge
39
+ # When we <action> storage for the mysql-5.1 cartridge
40
+ # Then the additional cartridge storage amount should be <total>
41
+ #
42
+ # Examples:
43
+ # | action | total |
44
+ # | show | None |
45
+ # | add 5GB | 5GB |
46
+ # | remove 3GB | 2GB |
47
+ # | set 4GB | 4GB |
@@ -17,7 +17,7 @@ Feature: Existing Domain Operations
17
17
 
18
18
  Scenario: Domain Create Fails
19
19
  When rhc domain create is called
20
- Then the domain command should fail with an exitcode of 128
20
+ Then the domain command should fail with an exitcode of 103
21
21
 
22
22
  Scenario: Domain Delete
23
23
  When domain is deleted
@@ -6,13 +6,13 @@ require 'tmpdir'
6
6
  module RHCHelper
7
7
  TEMP_DIR = File.join(Dir.tmpdir, "rhc") unless const_defined?(:TEMP_DIR)
8
8
  # The regex to parse the UUID output from the create app results
9
- UUID_OUTPUT_PATTERN = %r|UUID\s*=\s*(.+)| unless const_defined?(:UUID_OUTPUT_PATTERN)
9
+ UUID_OUTPUT_PATTERN = /UUID\s*(?:\:|=)\s*(.+)/i unless const_defined?(:UUID_OUTPUT_PATTERN)
10
10
  # The regex to parse the Gear Profile output from the create app results
11
- GEAR_PROFILE_OUTPUT_PATTERN = %r|Application Info.*Gear Size\s*=\s*(\w+)|m unless const_defined?(:GEAR_PROFILE_OUTPUT_PATTERN)
11
+ GEAR_PROFILE_OUTPUT_PATTERN = /Info.*Gear Size\s*(?:\:|=)\s*(\w+)/m unless const_defined?(:GEAR_PROFILE_OUTPUT_PATTERN)
12
12
  # Regex to parse passwords out of logging messages
13
13
  PASSWORD_REGEX = / -p [^\s]* / unless const_defined?(:PASSWORD_REGEX)
14
14
  end
15
-
15
+ \
16
16
  require 'rhc_helper/loggable'
17
17
  require 'rhc_helper/commandify'
18
18
  require 'rhc_helper/httpify'
@@ -36,15 +36,23 @@ module RHCHelper
36
36
  # 2 - password
37
37
  # 3 - upload SSH keys
38
38
  # 4 - if no namespace is found, create namespace? (blank is no)
39
+ args = [$username, $password]
40
+ args << 'yes' unless ($keyed_users ||= []).include?($username)
41
+ puts "User #{$username} has no keys" if args.length == 3
42
+ args << '' # always skip namespace
39
43
  if $namespace
40
44
  # Namespace is already created, so don't pass anything in
41
45
  logger.info("Namespace (#{$namespace}) should be found by the wizard")
42
- run("rhc setup", nil, [$username, $password, 'yes', ""])
46
+ run("rhc setup", nil, args) do |exitstatus, out, err, arg|
47
+ raise "Unmatched namespace #{$namespace}" unless out.include?($namespace)
48
+ end
43
49
  else
44
50
  # Pass in a blank value for namespace to create in the next step
51
+ args << ''
45
52
  logger.info("Skipping namespace creation")
46
- run("rhc setup", nil, [$username, $password, 'yes', "", ""])
53
+ run("rhc setup", nil, args)
47
54
  end
55
+ $keyed_users << $username
48
56
  end
49
57
 
50
58
  def self.create_unique(type, scalable, gear_profile=nil, prefix="test")
@@ -58,7 +66,7 @@ module RHCHelper
58
66
  test_names << app.name if app.name.start_with?(prefix)
59
67
  end
60
68
  end
61
-
69
+
62
70
  loop do
63
71
  # Generate a random application name
64
72
  chars = ("1".."9").to_a
@@ -78,6 +78,14 @@ module RHCHelper
78
78
  status
79
79
  end
80
80
 
81
+ def storage(cartridge, args)
82
+ output = nil
83
+ rhc_cartridge("storage #{cartridge} #{args}") do |exitstatus, out, err, arg|
84
+ output = out.split(" ")[-1]
85
+ end
86
+ output
87
+ end
88
+
81
89
  def show
82
90
  result = ""
83
91
  rhc_cartridge('show') do |exitstatus, out, err, arg|
@@ -27,13 +27,14 @@ module RHCHelper
27
27
 
28
28
  def self.create_if_needed(prefix="test")
29
29
  unless $namespace
30
- $namespace = unique_namespace(prefix)
31
- # Create the domain
32
- rhc_domain_create
33
-
34
- # Write the new domain to a file in the temp directory
35
- File.open(File.join(RHCHelper::TEMP_DIR, 'namespace'), 'w') do |f|
36
- f.write($namespace)
30
+ client = RHC::Rest::Client.new($end_point, $username, $password)
31
+ domain = client.domains.first
32
+ if domain
33
+ $namespace = domain.id
34
+ else
35
+ $namespace = unique_namespace(prefix)
36
+ # Create the domain
37
+ rhc_domain_create
37
38
  end
38
39
  end
39
40
  end
@@ -45,9 +46,6 @@ module RHCHelper
45
46
  def self.delete
46
47
  rhc_domain_delete
47
48
  $namespace = nil
48
- # Write the new domain to a file in the temp directory
49
- namespace_file = File.join(RHCHelper::TEMP_DIR, 'namespace')
50
- File.delete(namespace_file) if File.exists?(namespace_file)
51
49
  end
52
50
 
53
51
  def self.update(prefix="update")
@@ -55,12 +53,7 @@ module RHCHelper
55
53
  $namespace = unique_namespace(prefix)
56
54
  rhc_domain_update
57
55
 
58
- namespace_file = File.join(RHCHelper::TEMP_DIR, 'namespace')
59
56
  if @exitcode == 0
60
- # Write the new domain to a file in the temp directory
61
- File.open(namespace_file, 'w') do |f|
62
- f.write($namespace)
63
- end
64
57
  else
65
58
  $namespace = $old_namespace
66
59
  end
@@ -70,25 +70,26 @@ module RHCHelper
70
70
  begin
71
71
  timeout(options[:timeout]) do
72
72
  loop do
73
+ logger.debug "HTTP_CHECK: Requesting: #{uri}"
73
74
  # Send the HTTP request
74
75
  response = begin
75
76
  http = http_instance(uri,options[:http_timeout])
76
- logger.debug "Requesting: #{uri}"
77
77
  http.send_request(
78
78
  options[:method].to_s.upcase, # Allow options to be a symbol
79
79
  uri.request_uri, nil, headers
80
80
  )
81
81
  rescue Exception => e
82
82
  # Pass these up so we can check them
83
- return e
83
+ e
84
84
  end
85
-
85
+ logger.debug "HTTP_CHECK: Response: #{response.class}"
86
86
  case response
87
87
  # Catch any response if we're expecting it or redirection
88
88
  when expected.class, Net::HTTPRedirection
89
89
  break
90
90
  # Retry these responses
91
- when Net::HTTPServiceUnavailable, SocketError
91
+ when Net::HTTPServiceUnavailable, SocketError, Timeout::Error
92
+ logger.debug "HTTP_CHECK: Error #{response.message}"
92
93
  my_sleep(response,expected,start,options)
93
94
  else
94
95
  case expected
@@ -123,13 +124,17 @@ module RHCHelper
123
124
 
124
125
  def is_inaccessible?(options = {})
125
126
  check_response(options.merge({
126
- :expected => Net::HTTPServiceUnavailable
127
+ :expected => Net::HTTPServiceUnavailable,
128
+ :http_timeout => 2,
129
+ :timeout => 60,
127
130
  }))
128
131
  end
129
132
 
130
133
  def is_accessible?(options = {})
131
134
  check_response(options.merge({
132
- :expected => Net::HTTPSuccess
135
+ :expected => Net::HTTPSuccess,
136
+ :http_timeout => 20,
137
+ :timeout => 180,
133
138
  }))
134
139
  end
135
140
 
@@ -1,10 +1,28 @@
1
1
  require 'open4'
2
2
  require 'timeout'
3
+ require 'iconv'
4
+ require 'rubygems'
3
5
 
4
6
  module RHCHelper
5
7
  module Runnable
6
8
  include Loggable
7
9
 
10
+ class StringTee < StringIO
11
+ attr_reader :tee
12
+ def initialize(other)
13
+ @tee = other
14
+ super()
15
+ end
16
+ def <<(buf)
17
+ tee << buf
18
+ super
19
+ end
20
+ end
21
+
22
+ def iconv_handler
23
+ @iconv ||= Iconv.new('UTF-8//IGNORE', 'UTF-8')
24
+ end
25
+
8
26
  def run(cmd, arg=nil, input=[])
9
27
  logger.info("Running: #{cmd}")
10
28
 
@@ -12,17 +30,35 @@ module RHCHelper
12
30
  output = nil
13
31
 
14
32
  # Don't let a command run more than 5 minutes
15
- Timeout::timeout(500) do
16
- pid, stdin, stdout, stderr = Open4::popen4 cmd
17
- input.each {|line| stdin.puts line}
18
- stdin.close
33
+ Timeout::timeout(240) do
34
+
35
+ stdout, stderr = (ENV['VERBOSE'] ? [$stdout, $stderr] : [logger, logger]).map{ |t| StringTee.new(t) }
36
+ stdin = input.inject(StringIO.new){ |io, s| io.puts s; io }
37
+ stdin.close_write
38
+ stdin.rewind
39
+ status = Open4.spawn(cmd, 'stdout' => stdout, 'stderr' => stderr, 'stdin' => stdin, 'quiet' => true)
40
+ out, err = [stdout, stderr].map(&:string)
41
+
42
+ #pid, stdin, stdout, stderr = Open4::popen4 cmd
43
+ #input.each {|line| stdin.puts line}
44
+ #stdin.close
19
45
 
20
46
  # Block until the command finishes
21
- ignored, status = Process::waitpid2 pid
22
- out = stdout.read.strip
23
- err = stderr.read.strip
47
+ #ignored, status = Process::waitpid2 pid
48
+ #out = stdout.read.strip
49
+ #err = stderr.read.strip
24
50
  stdout.close
25
51
  stderr.close
52
+
53
+ # Force the output to ASCII-only characters or logger will barf.
54
+ if (Gem::Version.new(RUBY_VERSION.dup) <=> Gem::Version.new('1.9.3')) >= 0
55
+ out.encode!('UTF-8', 'UTF-8', :undef => :replace, :invalid => :replace)
56
+ err.encode!('UTF-8', 'UTF-8', :undef => :replace, :invalid => :replace)
57
+ else
58
+ out = iconv_handler.iconv(out + ' ')[0..-2]
59
+ err = iconv_handler.iconv(err + ' ')[0..-2]
60
+ end
61
+
26
62
  logger.debug("Standard Output:\n#{out}")
27
63
  logger.debug("Standard Error:\n#{err}")
28
64
 
@@ -28,7 +28,7 @@ As an OpenShift user, I want to manage SSH keys with 'rhc sshkey' commands.
28
28
  @sshkey_add
29
29
  Scenario: invalid key name is given
30
30
  When a new SSH key "key1.pub" is added as "blah\\ss"
31
- Then the command exits with status code 128
31
+ Then the command exits with status code 117
32
32
 
33
33
  @sshkey_add
34
34
  Scenario: invalid SSH key is added
@@ -43,14 +43,13 @@ As an OpenShift user, I want to manage SSH keys with 'rhc sshkey' commands.
43
43
  @sshkey_add @key1
44
44
  Scenario: SSH key with the same name already exists
45
45
  When a new SSH key "key2.pub" is added as "key1"
46
- Then the command exits with status code 128
46
+ Then the command exits with status code 120
47
47
 
48
48
  @sshkey_add
49
49
  Scenario: SSH key with the identical content already exists
50
50
  Given a new SSH key "key1.pub" is added as "key1"
51
51
  And a new SSH key "key1.pub" is added as "key2"
52
- Then the command exits with status code 128
53
-
52
+ Then the command exits with status code 121
54
53
 
55
54
  @sshkey_remove @key1
56
55
  Scenario: SSH key is deleted successfully
@@ -25,9 +25,9 @@ Given /^an existing (or new )?(scaled )?(.+) (application with.*)$/ do |create,
25
25
  @app = nil if @app.nil? or not @app.is_created?
26
26
 
27
27
  if create && @app.nil?
28
- When "a #{scaled}#{type} application is created"
28
+ step "a #{scaled}#{type} application is created"
29
29
  embeds.each do |embed|
30
- When "the #{embed} cartridge is added"
30
+ step "the #{embed} cartridge is added"
31
31
  end
32
32
  end
33
33
 
@@ -45,7 +45,7 @@ end
45
45
  When /^(\d+) (.+) applications are created$/ do |app_count, type|
46
46
  old_app = @app
47
47
  @apps = app_count.to_i.times.collect do
48
- Then "a #{type} application is created"
48
+ step "a #{type} application is created"
49
49
  @app
50
50
  end
51
51
  @app = old_app
@@ -88,7 +88,7 @@ end
88
88
  Then /^the applications should be accessible?$/ do
89
89
  old_app = @app
90
90
  @apps.each do |app|
91
- Then "the application should be accessible"
91
+ step "the application should be accessible"
92
92
  end
93
93
  @app = old_app
94
94
  end
@@ -110,7 +110,7 @@ Then /^it should succeed$/ do
110
110
  end
111
111
 
112
112
  Then /^the application should be scalable/ do
113
- Then "the haproxy-1.4 cartridge should be running"
113
+ step "the haproxy-1.4 cartridge should be running"
114
114
  end
115
115
 
116
116
  Then /^the application should have a (.*) gear$/ do |gear_profile|
@@ -19,6 +19,8 @@ When /^the (.+) cartridge is (stopped|(?:re)?started)$/ do |name,command|
19
19
  'start'
20
20
  when :restarted
21
21
  'restart'
22
+ else
23
+ raise "Unrecognized command type #{status}"
22
24
  end
23
25
  @app.cartridge(name).send(cmd)
24
26
  end
@@ -31,6 +33,8 @@ Then /^the (.+) cartridge should be (.*)$/ do |name,status|
31
33
  "(.+) stopped"
32
34
  when :removed
33
35
  "Invalid cartridge specified: '#{name}'"
36
+ else
37
+ raise "Unrecognized status type #{status}"
34
38
  end
35
39
  @app.cartridge(name).status.should match(expected)
36
40
  end
@@ -51,6 +55,10 @@ When /^we list cartridges$/ do
51
55
  @exitcode, @cartridge_output = Cartridge.list
52
56
  end
53
57
 
58
+ When /^we (.+) storage for the (.+) cartridge$/ do |storage_action,cartridge|
59
+ @output = @app.cartridge(@cartridge_name).send(:storage, cartridge, "--#{storage_action}")
60
+ end
61
+
54
62
  Then /^the (\w+) scaling value should be (.*)$/ do |minmax,value|
55
63
  expected = {
56
64
  :min => "Minimum",
@@ -65,6 +73,10 @@ Then /^the (\w+) scaling value should be (.*)$/ do |minmax,value|
65
73
  @app.cartridge(@cartridge_name).send(:show).should match(regex)
66
74
  end
67
75
 
76
+ Then /^the additional cartridge storage amount should be (\w+)$/ do |value|
77
+ @output.should == value
78
+ end
79
+
68
80
  Then /^it should fail with code (\d+)$/ do |code|
69
81
  @exitcode.should == code.to_i
70
82
  end
@@ -22,6 +22,7 @@ Given /^the libra client tools$/ do
22
22
  end
23
23
 
24
24
  When /^the setup wizard is run$/ do
25
+ puts "Running setup"
25
26
  RHCHelper::App.rhc_setup
26
27
 
27
28
  # Force a refresh of the loaded RHC state
@@ -29,10 +30,10 @@ When /^the setup wizard is run$/ do
29
30
  end
30
31
 
31
32
  Then /^the client tools should be setup( if needed)?$/ do |setup|
32
- configured = (RHC::Config.has_local_config? or RHC::Config.has_opts_config?)
33
+ configured = (RHC::Config.default_rhlogin && RHC::Config.default_rhlogin == $username && $keyed_users.include?($username))
33
34
 
34
35
  if !configured && setup
35
- Then 'the setup wizard is run'
36
+ step 'the setup wizard is run'
36
37
  configured = (RHC::Config.has_local_config? or RHC::Config.has_opts_config?)
37
38
  end
38
39
 
@@ -9,7 +9,7 @@ When /^'rhc sshkey (\S+)( .*?)?'(?: command)? is run$/ do |subcommand, rest|
9
9
  end
10
10
 
11
11
  Given "the existing keys are listed" do
12
- When "'rhc sshkey list' is run"
12
+ step "'rhc sshkey list' is run"
13
13
  end
14
14
 
15
15
  Given /^the key "(.*?)" is (.*)$/ do |key,cmd|
@@ -19,12 +19,12 @@ Given /^the key "(.*?)" is (.*)$/ do |key,cmd|
19
19
  when "removed"
20
20
  "remove"
21
21
  end
22
- When "'rhc sshkey #{cmd} \"#{key}\"' is run"
22
+ step "'rhc sshkey #{cmd} \"#{key}\"' is run"
23
23
  end
24
24
 
25
25
  When /^a new SSH key "(.*?)" is added as "(.*)"$/ do |keyfile, name|
26
26
  keyfile = Sshkey.keyfile_path(keyfile)
27
- When "'rhc sshkey add #{name} #{keyfile}' is run"
27
+ step "'rhc sshkey add #{name} #{keyfile}' is run"
28
28
  end
29
29
 
30
30
  Then /^the command exits with status code (\d+)$/ do |arg1|
@@ -1,16 +1,16 @@
1
1
  Given 'we have the client tools setup' do
2
- When 'the libra client tools'
3
- When 'the client tools should be setup if needed'
2
+ step 'the libra client tools'
3
+ step 'the client tools should be setup if needed'
4
4
  end
5
5
 
6
6
  Given 'we have an existing domain' do
7
- When 'we have the client tools setup'
8
- When 'a new domain is needed and created'
7
+ step 'we have the client tools setup'
8
+ step 'a new domain is needed and created'
9
9
  begin
10
- When 'the key "key1" is shown'
11
- Then 'the output includes the key information for "key1"'
10
+ step 'the key "key1" is shown'
11
+ step 'the output includes the key information for "key1"'
12
12
  rescue Spec::Expectations::ExpectationNotMetError
13
- Given 'a new SSH key "key1.pub" is added as "key1"'
13
+ step 'a new SSH key "key1.pub" is added as "key1"'
14
14
  end
15
15
  end
16
16
 
@@ -26,9 +26,9 @@ Given /^we have a (.*) (.*) cartridge$/ do |status,type|
26
26
  # only try once
27
27
  retried = false
28
28
  begin
29
- When "the #{type} cartridge should be #{status}"
29
+ step "the #{type} cartridge should be #{status}"
30
30
  rescue Spec::Expectations::ExpectationNotMetError
31
- When "the #{type} cartridge is #{cmd}"
31
+ step "the #{type} cartridge is #{cmd}"
32
32
  (retried = true && retry) unless retried
33
33
  end
34
34
  end
@@ -42,8 +42,8 @@ Given /^we have a (stopped|running) application$/ do |state|
42
42
  end
43
43
 
44
44
  begin
45
- When "the application should #{before}"
45
+ step "the application should #{before}"
46
46
  rescue Spec::Expectations::ExpectationNotMetError
47
- When "the application is #{after}"
47
+ step "the application is #{after}"
48
48
  end
49
49
  end