rhc 0.94.8 → 0.95.13

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 (59) hide show
  1. data/README.md +27 -1
  2. data/bin/rhc +15 -23
  3. data/bin/rhc-app +4 -1
  4. data/bin/rhc-chk +3 -0
  5. data/bin/rhc-create-app +3 -0
  6. data/bin/rhc-create-domain +3 -0
  7. data/bin/rhc-ctl-app +3 -0
  8. data/bin/rhc-ctl-domain +3 -0
  9. data/bin/rhc-domain +5 -2
  10. data/bin/rhc-domain-info +3 -0
  11. data/bin/rhc-port-forward +16 -18
  12. data/bin/rhc-snapshot +3 -0
  13. data/bin/rhc-sshkey +3 -0
  14. data/bin/rhc-tail-files +3 -0
  15. data/bin/rhc-user-info +1 -0
  16. data/features/README.md +70 -0
  17. data/features/lib/rhc_helper/app.rb +124 -0
  18. data/features/lib/rhc_helper/cartridge.rb +72 -0
  19. data/features/lib/rhc_helper/commandify.rb +154 -0
  20. data/features/lib/rhc_helper/domain.rb +50 -0
  21. data/features/lib/rhc_helper/httpify.rb +107 -0
  22. data/features/lib/rhc_helper/loggable.rb +39 -0
  23. data/features/lib/rhc_helper/persistable.rb +38 -0
  24. data/features/lib/rhc_helper/runnable.rb +41 -0
  25. data/features/lib/rhc_helper.rb +7 -0
  26. data/features/step_definitions/application_steps.rb +99 -0
  27. data/features/step_definitions/cartridge_steps.rb +42 -0
  28. data/features/step_definitions/client_steps.rb +32 -0
  29. data/features/step_definitions/domain_steps.rb +19 -0
  30. data/features/support/env.rb +99 -0
  31. data/features/verify.feature +123 -0
  32. data/lib/rhc/cli.rb +4 -1
  33. data/lib/rhc/commands/base.rb +28 -6
  34. data/lib/rhc/commands/server.rb +4 -1
  35. data/lib/rhc/commands/setup.rb +24 -0
  36. data/lib/rhc/commands.rb +10 -5
  37. data/lib/rhc/config.rb +90 -21
  38. data/lib/rhc/core_ext.rb +11 -2
  39. data/lib/rhc/coverage_helper.rb +35 -0
  40. data/lib/rhc/help_formatter.rb +30 -0
  41. data/lib/rhc/helpers.rb +41 -5
  42. data/lib/rhc/ssh_key_helpers.rb +72 -0
  43. data/lib/rhc/targz.rb +2 -8
  44. data/lib/rhc/wizard.rb +75 -58
  45. data/lib/rhc-common.rb +20 -13
  46. data/lib/rhc-rest.rb +3 -11
  47. data/spec/coverage_helper.rb +51 -0
  48. data/spec/rest_spec_helper.rb +86 -0
  49. data/spec/rhc/cli_spec.rb +19 -3
  50. data/spec/rhc/commands/server_spec.rb +2 -2
  51. data/spec/rhc/common_spec.rb +49 -0
  52. data/spec/rhc/config_spec.rb +328 -0
  53. data/spec/rhc/helpers_spec.rb +74 -1
  54. data/spec/rhc/rest_client_spec.rb +402 -0
  55. data/spec/rhc/rest_spec.rb +454 -0
  56. data/spec/rhc/targz_spec.rb +13 -0
  57. data/spec/rhc/wizard_spec.rb +305 -43
  58. data/spec/spec_helper.rb +30 -25
  59. metadata +124 -5
@@ -0,0 +1,154 @@
1
+ require 'benchmark'
2
+ require 'fileutils'
3
+
4
+ module RHCHelper
5
+ module Commandify
6
+ # Implements a method missing approach that will convert calls
7
+ # like rhc_app_create into 'rhc app create' on the command line
8
+ def method_missing(sym, *args, &block)
9
+ if sym.to_s.start_with?("rhc")
10
+ # Build up the command
11
+ cmd = get_cmd(sym)
12
+
13
+ # Get any blocks that should be run after processing
14
+ cmd_callback = get_cmd_callback(cmd, args[0])
15
+
16
+ # Add arguments to the command
17
+ cmd << get_args(cmd, args[0])
18
+
19
+ # Run the command, timing it
20
+ time = Benchmark.realtime do
21
+ run(cmd, args[0], &cmd_callback).should == 0
22
+ end
23
+
24
+ # Log the benchmarking info
25
+ perf_logger.info "#{time} #{sym.to_s.upcase} #{$namespace} #{$login}"
26
+ else
27
+ super(sym, *args, &block)
28
+ end
29
+ end
30
+
31
+ # Given a method name, convert to an equivalent
32
+ # rhc command line string. This method handles
33
+ # exceptions like converting rhc_app_add_alias
34
+ # to rhc app add-alias.
35
+ def get_cmd(method_sym)
36
+ cmd = method_sym.to_s.gsub('_', ' ')
37
+
38
+ # Handle parameters with a dash
39
+ cmd.gsub!('add alias', 'add-alias')
40
+ cmd.gsub!('remove alias', 'remove-alias')
41
+ cmd.gsub!('force stop', 'force-stop')
42
+
43
+ return cmd
44
+ end
45
+
46
+ # Print out the command arguments based on the state of the application instance
47
+ def get_args(cmd, cartridge=nil, debug=true)
48
+ args = " "
49
+ args << "-l #{$username} "
50
+ args << "-p #{$password} "
51
+ args << "-d " if debug
52
+
53
+ # Add the application name for all application commands
54
+ if cmd =~ /app/
55
+ raise "No application name" unless @name
56
+ args << "-a #{@name} "
57
+ end
58
+
59
+ # Command specific arguments
60
+ case cmd
61
+ when /domain/
62
+ raise "No namespace set" unless $namespace
63
+ args << "-n #{$namespace} "
64
+ when /destroy/
65
+ args << "-b "
66
+ when /snapshot/
67
+ args << "-f #{@snapshot} "
68
+ when /create/
69
+ args << "-r #{@repo} "
70
+ args << "-t #{@type} "
71
+ when /add-alias/
72
+ raise "No alias set" unless @alias
73
+ args << "--alias #{@alias} "
74
+ when /cartridge/
75
+ raise "No cartridge supplied" unless cartridge
76
+ args << "-c #{cartridge}"
77
+ end
78
+
79
+ args.rstrip
80
+ end
81
+
82
+ # This looks for a callback method that is defined for the command.
83
+ # For example, a command with rhc_app_create_callback will match
84
+ # and be returned for the 'rhc app create' command. The most specific
85
+ # callback will be matched, so rhc_app_create_callback being more
86
+ # specific than rhc_app_callback.
87
+ def get_cmd_callback(cmd, cartridge=nil)
88
+ # Break the command up on spaces
89
+ cmd_parts = cmd.split
90
+
91
+ # Drop the 'rhc' portion from the array
92
+ cmd_parts.shift
93
+
94
+ # Look for a method match ending in _callback
95
+ cmd_parts.length.times do
96
+ begin
97
+ # Look for a callback match and return on any find
98
+ return method((cmd_parts.join("_") + "_callback").to_sym)
99
+ rescue NameError
100
+ # Remove one of the parts to see if there is a more
101
+ # generic match defined
102
+ cmd_parts.pop
103
+ end
104
+ end
105
+
106
+ return nil
107
+ end
108
+ end
109
+
110
+ # The regex to parse the ssh output from the create app results
111
+ SSH_OUTPUT_PATTERN = %r|ssh://([^@]+)@([^/]+)|
112
+
113
+ #
114
+ # Begin Post Processing Callbacks
115
+ #
116
+ def app_create_callback(exitcode, stdout, stderr, arg)
117
+ match = stdout.split.map {|line| line.match(SSH_OUTPUT_PATTERN)}.compact[0]
118
+ @uid = match[1] if match
119
+ raise "UID not parsed from app create output" unless @uid
120
+ persist
121
+ end
122
+
123
+ def app_destroy_callback(exitcode, stdout, stderr, arg)
124
+ FileUtils.rm_rf @repo
125
+ FileUtils.rm_rf @file
126
+ @repo, @file = nil
127
+ end
128
+
129
+ def cartridge_add_callback(exitcode, stdout, stderr, cartridge)
130
+ if cartridge.start_with?('mysql-')
131
+ @mysql_hostname = /^Connection URL: mysql:\/\/(.*)\/$/.match(stdout)[1]
132
+ @mysql_user = /^ +Root User: (.*)$/.match(stdout)[1]
133
+ @mysql_password = /^ +Root Password: (.*)$/.match(stdout)[1]
134
+ @mysql_database = /^ +Database Name: (.*)$/.match(stdout)[1]
135
+
136
+ @mysql_hostname.should_not be_nil
137
+ @mysql_user.should_not be_nil
138
+ @mysql_password.should_not be_nil
139
+ @mysql_database.should_not be_nil
140
+ end
141
+
142
+ @embed << cartridge
143
+ persist
144
+ end
145
+
146
+ def cartridge_remove_callback(exitcode, stdout, stderr, cartridge)
147
+ @mysql_hostname = nil
148
+ @mysql_user = nil
149
+ @mysql_password = nil
150
+ @mysql_database = nil
151
+ @embed.delete(cartridge)
152
+ persist
153
+ end
154
+ end
@@ -0,0 +1,50 @@
1
+ require 'dnsruby'
2
+ require 'rhc-rest'
3
+
4
+ module RHCHelper
5
+ #
6
+ # A class to help maintain the state from rhc calls
7
+ #
8
+ class Domain
9
+ extend Runnable
10
+ extend Commandify
11
+ include Dnsruby
12
+
13
+ def self.create_if_needed(prefix="test")
14
+ unless $namespace
15
+ loop do
16
+ # Loop until we find a unique namespace
17
+ chars = ("1".."9").to_a
18
+ namespace = prefix + Array.new(8, '').collect{chars[rand(chars.size)]}.join
19
+
20
+ # No retries on reservation check
21
+ unless reserved?(namespace)
22
+ # Set the global namespace
23
+ $namespace = namespace
24
+
25
+ # Create the domain
26
+ rhc_domain_create
27
+
28
+ # Write the new domain to a file in the temp directory
29
+ File.open(File.join(RHCHelper::TEMP_DIR, 'namespace'), 'w') do |f|
30
+ f.write(namespace)
31
+ end
32
+
33
+ break
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.reserved?(namespace=$namespace)
40
+ # If we get a response, then the namespace is reserved
41
+ # An exception means that it is available
42
+ begin
43
+ Dnsruby::Resolver.new.query("#{namespace}.#{$domain}", Dnsruby::Types::TXT)
44
+ return true
45
+ rescue
46
+ return false
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,107 @@
1
+ require 'uri'
2
+ require 'net/https'
3
+ require 'ostruct'
4
+
5
+ module RHCHelper
6
+ module Httpify
7
+ include Loggable
8
+
9
+ # attributes that contain statistics based on calls to connect
10
+ attr_accessor :response_code, :response_time
11
+
12
+ def http_instance(uri, timeout=30)
13
+ proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new
14
+ http = Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port)
15
+ http.open_timeout = timeout
16
+ http.read_timeout = timeout
17
+ if (uri.scheme == "https")
18
+ http.use_ssl = true
19
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
20
+ end
21
+ return http.start
22
+ end
23
+
24
+ def http_get(url, timeout=30)
25
+ uri = URI.parse(url)
26
+ http = http_instance(uri, timeout)
27
+ request = Net::HTTP::Get.new(uri.request_uri)
28
+ http.request(request)
29
+ end
30
+
31
+ def http_head(url, host=nil, follow_redirects=true)
32
+ uri = URI.parse(url)
33
+ http = http_instance(uri)
34
+ request = Net::HTTP::Head.new(uri.request_uri)
35
+ request["Host"] = host if host
36
+ response = http.request(request)
37
+
38
+ if follow_redirects and response.is_a?(Net::HTTPRedirection)
39
+ return http_head(response.header['location'])
40
+ else
41
+ return response
42
+ end
43
+ end
44
+
45
+ def is_inaccessible?(max_retries=120)
46
+ max_retries.times do |i|
47
+ begin
48
+ if http_head("http://#{hostname}").is_a? Net::HTTPServerError
49
+ return true
50
+ else
51
+ logger.info("Connection still accessible / retry #{i} / #{hostname}")
52
+ sleep 1
53
+ end
54
+ rescue
55
+ return true
56
+ end
57
+ end
58
+ return false
59
+ end
60
+
61
+ def is_accessible?(use_https=false, max_retries=120, host=nil)
62
+ prefix = use_https ? "https://" : "http://"
63
+ url = prefix + hostname
64
+
65
+ max_retries.times do |i|
66
+ begin
67
+ if http_head(url, host).is_a? Net::HTTPSuccess
68
+ return true
69
+ else
70
+ logger.info("Connection still inaccessible / retry #{i} / #{url}")
71
+ sleep 1
72
+ end
73
+ rescue SocketError
74
+ logger.info("Connection still inaccessible / retry #{i} / #{url}")
75
+ sleep 1
76
+ end
77
+ end
78
+
79
+ return false
80
+ end
81
+
82
+ def connect(use_https=false, max_retries=30)
83
+ prefix = use_https ? "https://" : "http://"
84
+ url = prefix + hostname
85
+
86
+ logger.info("Connecting to #{url}")
87
+ beginning_time = Time.now
88
+
89
+ max_retries.times do |i|
90
+ response = http_get(url, 1)
91
+
92
+ if response.is_a? Net::HTTPSuccess
93
+ @response_code = response.code
94
+ @response_time = Time.now - beginning_time
95
+ logger.info("Connection result = #{@response_code} / #{url}")
96
+ logger.info("Connection response time = #{@response_time} / #{url}")
97
+ return response.body
98
+ else
99
+ logger.info("Connection failed / retry #{i} / #{url}")
100
+ sleep 1
101
+ end
102
+ end
103
+
104
+ return nil
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,39 @@
1
+ require 'logger'
2
+
3
+ module RHCHelper
4
+ module Loggable
5
+ PASSWORD_REGEX = / -p [^\s]* /
6
+
7
+ def logger
8
+ Loggable.logger
9
+ end
10
+
11
+ def perf_logger
12
+ Loggable.perf_logger
13
+ end
14
+
15
+ def self.logger
16
+ @logger ||= Logger.new($stdout)
17
+ end
18
+
19
+ def self.logger=(logger)
20
+ @logger = logger
21
+ original_formatter = Logger::Formatter.new
22
+ @logger.formatter = proc { |severity, datetime, progname, msg|
23
+ # Filter out any passwords
24
+ filter_msg = msg.gsub(PASSWORD_REGEX, " -p ***** ")
25
+
26
+ # Format with the original formatter
27
+ original_formatter.call(severity, datetime, progname, filter_msg)
28
+ }
29
+ end
30
+
31
+ def self.perf_logger
32
+ @perf_logger ||= Logger.new($stdout)
33
+ end
34
+
35
+ def self.perf_logger=(logger)
36
+ @perf_logger = logger
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_support/json'
2
+ require 'active_support/core_ext/object/to_json'
3
+
4
+ module RHCHelper
5
+ module Persistable
6
+ include ActiveSupport::JSON
7
+ include Loggable
8
+
9
+ def find_on_fs
10
+ Dir.glob("#{RHCHelper::TEMP_DIR}/*.json").collect {|f| App.from_file(f)}
11
+ end
12
+
13
+ def from_file(filename)
14
+ App.from_json(ActiveSupport::JSON.decode(File.open(filename, "r") {|f| f.readlines}[0]))
15
+ end
16
+
17
+ def from_json(json)
18
+ app = App.new(json['type'], json['name'])
19
+ app.embed = json['embed']
20
+ app.mysql_user = json['mysql_user']
21
+ app.mysql_password = json['mysql_password']
22
+ app.mysql_hostname = json['mysql_hostname']
23
+ app.uid = json['uid']
24
+ return app
25
+ end
26
+ end
27
+
28
+ module Persistify
29
+ include ActiveSupport::JSON
30
+
31
+ attr_accessor :file
32
+
33
+ def persist
34
+ json = self.to_json(:except => [:logger, :perf_logger])
35
+ File.open(@file, "w") {|f| f.puts json}
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ require 'open4'
2
+ require 'timeout'
3
+
4
+ module RHCHelper
5
+ module Runnable
6
+ include Loggable
7
+
8
+ def run(cmd, arg=nil, input=[])
9
+ logger.info("Running: #{cmd}")
10
+
11
+ exit_code = -1
12
+ output = nil
13
+
14
+ # 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
19
+
20
+ # Block until the command finishes
21
+ ignored, status = Process::waitpid2 pid
22
+ out = stdout.read.strip
23
+ err = stderr.read.strip
24
+ stdout.close
25
+ stderr.close
26
+ logger.debug("Standard Output:\n#{out}")
27
+ logger.debug("Standard Error:\n#{err}")
28
+
29
+ # Allow a caller to pass in a block to process the output
30
+ yield status.exitstatus, out, err, arg if block_given?
31
+ exit_code = status.exitstatus
32
+ end
33
+
34
+ if exit_code != 0
35
+ logger.error("(#{$$}): Execution failed #{cmd} with exit_code: #{exit_code.to_s}")
36
+ end
37
+
38
+ return exit_code
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ require 'rhc_helper/loggable'
2
+ require 'rhc_helper/commandify'
3
+ require 'rhc_helper/httpify'
4
+ require 'rhc_helper/persistable'
5
+ require 'rhc_helper/runnable'
6
+ require 'rhc_helper/app'
7
+ require 'rhc_helper/domain'
@@ -0,0 +1,99 @@
1
+ require 'fileutils'
2
+ require 'rhc/config'
3
+
4
+ include RHCHelper
5
+
6
+ Given /^an existing (.+) application with an embedded (.*) cartridge$/ do |type, embed|
7
+ App.find_on_fs.each do |app|
8
+ if app.type == type and app.embed.include?(embed)
9
+ @app = app
10
+ break
11
+ end
12
+ end
13
+
14
+ @app.should_not be_nil, 'No existing applications w/cartridges found. Check the creation scenarios for failures.'
15
+ end
16
+
17
+ Given /^an existing (.+) application with embedded (.*) and (.*) cartridges$/ do |type, embed_1, embed_2|
18
+ App.find_on_fs.each do |app|
19
+ if app.type == type and app.embed.include?(embed_1) and app.embed.include?(embed_2)
20
+ @app = app
21
+ break
22
+ end
23
+ end
24
+
25
+ @app.should_not be_nil, 'No existing applications w/cartridges found. Check the creation scenarios for failures.'
26
+ end
27
+
28
+ Given /^an existing (.+) application( without an embedded cartridge)?$/ do |type, ignore|
29
+ App.find_on_fs.each do |app|
30
+ if app.type == type and app.embed.empty?
31
+ @app = app
32
+ break
33
+ end
34
+ end
35
+
36
+ @app.should_not be_nil, 'No existing applications found. Check the creation scenarios for failures.'
37
+ end
38
+
39
+ When /^(\d+) (.+) applications are created$/ do |app_count, type|
40
+ @apps = app_count.to_i.times.collect do
41
+ app = App.create_unique(type)
42
+ app.rhc_app_create
43
+ app
44
+ end
45
+ end
46
+
47
+ When /^the application is stopped$/ do
48
+ @app.rhc_app_stop
49
+ end
50
+
51
+ When /^the application is started$/ do
52
+ @app.rhc_app_start
53
+ end
54
+
55
+ When /^the application is restarted$/ do
56
+ @app.rhc_app_restart
57
+ end
58
+
59
+ When /^the application is destroyed$/ do
60
+ @app.rhc_app_destroy
61
+ end
62
+
63
+ When /^the application is snapshot$/ do
64
+ @snapshot = File.join(RHCHelper::TEMP_DIR, "snapshot.tar.gz")
65
+ @app.snapshot = @snapshot
66
+ @app.rhc_app_snapshot_save
67
+ end
68
+
69
+ When /^the application is shown$/ do
70
+ @app.rhc_app_show
71
+ end
72
+
73
+ When /^the application is tidied$/ do
74
+ @app.rhc_app_tidy
75
+ end
76
+
77
+ Then /^the snapshot should be found$/ do
78
+ File.exist?(@snapshot).should be_true
79
+ (File.size(@snapshot) > 0).should be_true
80
+ end
81
+
82
+ Then /^the applications should be accessible?$/ do
83
+ @apps.each do |app|
84
+ app.is_accessible?.should be_true
85
+ app.is_accessible?(true).should be_true
86
+ end
87
+ end
88
+
89
+ Then /^the application should be accessible$/ do
90
+ @app.is_accessible?.should be_true
91
+ @app.is_accessible?(true).should be_true, "Application was not accessible and should be"
92
+ end
93
+
94
+ Then /^the application should not be accessible$/ do
95
+ @app.is_inaccessible?.should be_true, "Application was still accessible when it shouldn't be"
96
+ end
97
+
98
+ Then /^it should succeed$/ do
99
+ end
@@ -0,0 +1,42 @@
1
+ require 'fileutils'
2
+ require 'rhc/config'
3
+
4
+ include RHCHelper
5
+
6
+ When /^the (.+) cartridge is added$/ do |name|
7
+ @app.add_cartridge name
8
+ end
9
+
10
+ When /^the (.+) cartridge is stopped$/ do |name|
11
+ @app.cartridge(name).stop
12
+ end
13
+
14
+ When /^the (.+) cartridge is restarted$/ do |name|
15
+ @app.cartridge(name).restart
16
+ end
17
+
18
+ When /^the (.+) cartridge is started$/ do |name|
19
+ @app.cartridge(name).start
20
+ end
21
+
22
+ When /^the (.+) cartridge is removed$/ do |name|
23
+ @app.remove_cartridge name
24
+ end
25
+
26
+ Then /^the (.+) cartridge should be running$/ do |name|
27
+ @app.cartridge(name).status.should match("RESULT:\n(.+) is running|RESULT:\n(\n|.)+Uptime:")
28
+ end
29
+
30
+ Then /^the (.+) cartridge should be stopped$/ do |name|
31
+ @app.cartridge(name).status.should match("RESULT:\n(.+) stopped")
32
+ end
33
+
34
+ Then /^the (.+) cartridge should be removed$/ do |name|
35
+ # for some reason the server returns Success when cart does not exist
36
+ @app.cartridge(name).status.should match("RESULT:\n(.*)Success")
37
+ end
38
+
39
+
40
+ Then /^adding the (.+) cartridge should fail$/ do |name|
41
+ @app.add_cartridge(name).should == 1
42
+ end
@@ -0,0 +1,32 @@
1
+ # Cross-platform way of finding an executable in the $PATH.
2
+ #
3
+ # which('ruby') #=> /usr/bin/ruby
4
+ #
5
+ # Solution found at: http://bit.ly/8dKQsa
6
+ #
7
+ def which(cmd)
8
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
9
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
10
+ exts.each { |ext|
11
+ exe = "#{path}/#{cmd}#{ext}"
12
+ return exe if File.executable? exe
13
+ }
14
+ end
15
+ return nil
16
+ end
17
+
18
+ Given /^the libra client tools$/ do
19
+ which('rhc').should_not be_nil
20
+ end
21
+
22
+ When /^the setup wizard is run$/ do
23
+ RHCHelper::App.rhc_setup
24
+
25
+ # Force a refresh of the loaded RHC state
26
+ RHC::Config.initialize
27
+ end
28
+
29
+ Then /^the client tools should be setup$/ do
30
+ RHC::Config.should_run_wizard?.should be_false, "Wizard still thinks it needs to be run"
31
+ end
32
+
@@ -0,0 +1,19 @@
1
+ include RHCHelper
2
+ When /^a new domain is needed and created$/ do
3
+ Domain.create_if_needed
4
+ end
5
+
6
+ Then /^the domain should be reserved?$/ do
7
+ # Sleep to allow DNS to propogate
8
+ sleep 5
9
+
10
+ # Check for up to a minute
11
+ resolved = false
12
+ 120.times do
13
+ resolved = Domain.reserved?
14
+ break if resolved
15
+ sleep 1
16
+ end
17
+
18
+ resolved.should be_true, 'Not able to lookup DNS TXT record in time.'
19
+ end