rhc 0.98.16 → 1.0.4
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.
- data/bin/rhc +7 -49
- data/bin/rhc-app +14 -3
- data/bin/rhc-chk +16 -16
- data/bin/rhc-create-app +2 -0
- data/bin/rhc-create-domain +1 -2
- data/bin/rhc-ctl-app +12 -3
- data/bin/rhc-ctl-domain +1 -2
- data/bin/rhc-domain +1 -2
- data/bin/rhc-domain-info +1 -2
- data/bin/rhc-port-forward +1 -2
- data/bin/rhc-snapshot +3 -0
- data/bin/rhc-sshkey +1 -2
- data/bin/rhc-tail-files +1 -1
- data/bin/rhc-user-info +1 -3
- data/features/application.feature +4 -1
- data/features/domain.feature +0 -4
- data/features/geared_application.feature +11 -0
- data/features/lib/rhc_helper/app.rb +16 -5
- data/features/lib/rhc_helper/cartridge.rb +25 -9
- data/features/lib/rhc_helper/commandify.rb +34 -7
- data/features/lib/rhc_helper/domain.rb +2 -2
- data/features/lib/rhc_helper/httpify.rb +24 -14
- data/features/lib/rhc_helper/persistable.rb +1 -1
- data/features/lib/rhc_helper/sshkey.rb +11 -7
- data/features/lib/rhc_helper.rb +5 -3
- data/features/multiple_cartridge.feature +1 -1
- data/features/scaled_application.feature +48 -0
- data/features/sshkey.feature +37 -31
- data/features/step_definitions/application_steps.rb +18 -7
- data/features/step_definitions/cartridge_steps.rb +29 -3
- data/features/step_definitions/domain_steps.rb +2 -2
- data/features/step_definitions/sshkey_steps.rb +34 -34
- data/features/support/assumptions.rb +21 -9
- data/features/support/before_hooks.rb +24 -6
- data/features/support/env.rb +45 -19
- data/lib/rhc/cartridge_helper.rb +27 -0
- data/lib/rhc/cli.rb +1 -1
- data/lib/rhc/command_runner.rb +31 -3
- data/lib/rhc/commands/alias.rb +38 -0
- data/lib/rhc/commands/app.rb +478 -0
- data/lib/rhc/commands/base.rb +42 -12
- data/lib/rhc/commands/cartridge.rb +189 -0
- data/lib/rhc/commands/domain.rb +11 -49
- data/lib/rhc/commands/port-forward.rb +0 -1
- data/lib/rhc/commands/setup.rb +2 -1
- data/lib/rhc/commands/snapshot.rb +118 -0
- data/lib/rhc/commands/sshkey.rb +24 -38
- data/lib/rhc/commands/tail.rb +24 -0
- data/lib/rhc/commands/threaddump.rb +16 -0
- data/lib/rhc/commands.rb +33 -7
- data/lib/rhc/config.rb +28 -12
- data/lib/rhc/context_helper.rb +19 -5
- data/lib/rhc/core_ext.rb +86 -0
- data/lib/rhc/exceptions.rb +44 -0
- data/lib/rhc/git_helper.rb +59 -0
- data/lib/rhc/helpers.rb +86 -5
- data/lib/rhc/output_helpers.rb +213 -0
- data/lib/rhc/rest/application.rb +134 -67
- data/lib/rhc/rest/base.rb +48 -0
- data/lib/rhc/rest/cartridge.rb +40 -44
- data/lib/rhc/rest/client.rb +127 -59
- data/lib/rhc/rest/domain.rb +29 -39
- data/lib/rhc/rest/gear_group.rb +10 -0
- data/lib/rhc/rest/key.rb +8 -23
- data/lib/rhc/rest/user.rb +8 -24
- data/lib/rhc/rest.rb +22 -11
- data/lib/rhc/ssh_key_helpers.rb +47 -0
- data/lib/rhc/usage_templates/help.erb +0 -1
- data/lib/rhc/version.rb +3 -3
- data/lib/rhc/wizard.rb +123 -225
- data/lib/rhc-common.rb +43 -62
- data/spec/rest_spec_helper.rb +159 -36
- data/spec/rhc/cli_spec.rb +29 -1
- data/spec/rhc/command_spec.rb +32 -35
- data/spec/rhc/commands/alias_spec.rb +123 -0
- data/spec/rhc/commands/app_spec.rb +414 -0
- data/spec/rhc/commands/cartridge_spec.rb +342 -0
- data/spec/rhc/commands/domain_spec.rb +8 -8
- data/spec/rhc/commands/setup_spec.rb +17 -6
- data/spec/rhc/commands/snapshot_spec.rb +140 -0
- data/spec/rhc/commands/sshkey_spec.rb +26 -4
- data/spec/rhc/commands/tail_spec.rb +34 -0
- data/spec/rhc/commands/threaddump_spec.rb +83 -0
- data/spec/rhc/config_spec.rb +39 -13
- data/spec/rhc/context_spec.rb +51 -0
- data/spec/rhc/helpers_spec.rb +52 -12
- data/spec/rhc/rest_application_spec.rb +16 -3
- data/spec/rhc/rest_client_spec.rb +144 -36
- data/spec/rhc/rest_spec.rb +1 -1
- data/spec/rhc/wizard_spec.rb +133 -232
- data/spec/spec_helper.rb +4 -3
- metadata +56 -31
- data/features/support/ssh.sh +0 -2
- data/spec/rhc/common_spec.rb +0 -49
data/lib/rhc/command_runner.rb
CHANGED
@@ -6,6 +6,21 @@ module RHC
|
|
6
6
|
commands.keys.find_all { |name| name if /^#{name}\b/.match arg_string }
|
7
7
|
end
|
8
8
|
|
9
|
+
def options_parse_trace
|
10
|
+
if @args.include? "--trace"
|
11
|
+
@args.delete "--trace"
|
12
|
+
return true
|
13
|
+
end
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def options_parse_version
|
18
|
+
if @args.include? "--version" or @args.include? "-v"
|
19
|
+
say version
|
20
|
+
exit 0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
9
24
|
# override so we can do our own error handling
|
10
25
|
def run!
|
11
26
|
trace = false
|
@@ -20,10 +35,23 @@ module RHC
|
|
20
35
|
return
|
21
36
|
end
|
22
37
|
global_option('-v', '--version', 'Display version information') { say version; return }
|
23
|
-
global_option('
|
38
|
+
global_option('--timeout seconds', Integer, 'Set the timeout in seconds for network commands') do |value|
|
39
|
+
# FIXME: Refactor so we don't have to use a global var here
|
40
|
+
$rest_timeout = value
|
41
|
+
end
|
42
|
+
|
43
|
+
# remove these because we monkey patch Commands to process all options
|
44
|
+
# at once, avoiding conflicts between the global and command options
|
45
|
+
# code left here just in case someone compares this with the original
|
46
|
+
# commander code
|
47
|
+
#parse_global_options
|
48
|
+
#remove_global_options options, @args
|
49
|
+
|
50
|
+
# special case --trace because we need to use it in the runner
|
51
|
+
trace = options_parse_trace
|
24
52
|
|
25
|
-
|
26
|
-
|
53
|
+
# special case --version so it is processed before an invalid command
|
54
|
+
options_parse_version
|
27
55
|
|
28
56
|
unless trace
|
29
57
|
begin
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rhc/commands/base'
|
2
|
+
require 'rhc/config'
|
3
|
+
require 'rhc-common'
|
4
|
+
module RHC::Commands
|
5
|
+
class Alias < Base
|
6
|
+
summary "Add or remove a custom domain name for the application"
|
7
|
+
syntax "<command> <application> <alias> [--namespace namespace]"
|
8
|
+
default_action :help
|
9
|
+
|
10
|
+
summary "Add a custom domain name for the application"
|
11
|
+
syntax "<application> <alias> [--namespace namespace]"
|
12
|
+
argument :app, "Application name (required)", []
|
13
|
+
argument :app_alias, "Custom domain name for the application", []
|
14
|
+
option ["-n", "--namespace namespace"], "Namespace of your application", :context => :namespace_context, :required => true
|
15
|
+
alias_action :"app add-alias", :root_command => true, :deprecated => true
|
16
|
+
def add(app, app_alias)
|
17
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
18
|
+
rest_app = rest_domain.find_application(app)
|
19
|
+
response = rest_app.add_alias(app_alias)
|
20
|
+
results { say response.messages.first } if response.messages
|
21
|
+
0
|
22
|
+
end
|
23
|
+
|
24
|
+
summary "Remove a custom domain name for the application"
|
25
|
+
syntax "<application> <alias> [--namespace namespace]"
|
26
|
+
argument :app, "Application name (required)", []
|
27
|
+
argument :app_alias, "Custom domain name for the application", []
|
28
|
+
option ["-n", "--namespace namespace"], "Namespace of your application", :context => :namespace_context, :required => true
|
29
|
+
alias_action :"app remove-alias", :root_command => true, :deprecated => true
|
30
|
+
def remove(app, app_alias)
|
31
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
32
|
+
rest_app = rest_domain.find_application(app)
|
33
|
+
response = rest_app.remove_alias(app_alias)
|
34
|
+
results { say response.messages.first } if response.messages
|
35
|
+
0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,478 @@
|
|
1
|
+
require 'rhc/commands/base'
|
2
|
+
require 'resolv'
|
3
|
+
require 'rhc/git_helper'
|
4
|
+
require 'rhc/cartridge_helper'
|
5
|
+
|
6
|
+
module RHC::Commands
|
7
|
+
class App < Base
|
8
|
+
summary "Commands for creating and managing applications"
|
9
|
+
description "Creates and controls an OpenShift application. To see the list of all applications use the rhc domain show command. Note that delete is not reversible and will stop your application and then remove the application and repo from the remote server. No local changes are made."
|
10
|
+
syntax "<action>"
|
11
|
+
default_action :help
|
12
|
+
|
13
|
+
summary "Create an application and adds it to a domain"
|
14
|
+
syntax "<name> <cartridge> [... <other cartridges>][--namespace namespace]"
|
15
|
+
option ["-n", "--namespace namespace"], "Namespace to add your application to", :context => :namespace_context, :required => true
|
16
|
+
option ["-g", "--gear-size size"], "The size of the gear for this app. Available gear sizes depend on the type of account you have."
|
17
|
+
option ["-s", "--scaling"], "Enable scaling for this application"
|
18
|
+
option ["-r", "--repo dir"], "Git Repo path (defaults to ./$app_name) (applicable to the create command)"
|
19
|
+
option ["--[no-]git"], "Only create remote space, don't pull it locally"
|
20
|
+
option ["--nogit"], "DEPRECATED! Only create remote space, don't pull it locally", :deprecated => {:key => :git, :value => false}
|
21
|
+
option ["--[no-]dns"], "Skip DNS check. Must be used in combination with --no-git"
|
22
|
+
option ["--enable-jenkins [server_name]"], "Indicates to create a Jenkins application (if not already available) and embed the Jenkins client into this application. The default name will be 'jenkins' if not specified. Note that --no-dns is ignored for the creation of the Jenkins application."
|
23
|
+
argument :name, "The name you wish to give your application", ["-a", "--app name"]
|
24
|
+
argument :cartridge, "The first cartridge added to the application. Usually a web framework", ["-t", "--type cartridge"]
|
25
|
+
argument :additional_cartridges, "A list of other cartridges such as databases you wish to add. Cartridges can also be added later using 'rhc cartridge add'", [], :arg_type => :list
|
26
|
+
def create(name, cartridge, additional_cartridges)
|
27
|
+
options.default \
|
28
|
+
:dns => true,
|
29
|
+
:git => true
|
30
|
+
|
31
|
+
warnings = []
|
32
|
+
header "Creating application '#{name}'"
|
33
|
+
paragraph do
|
34
|
+
table({"Namespace:" => options.namespace,
|
35
|
+
"Cartridge:" => cartridge,
|
36
|
+
"Gear Size:" => options.gear_size || "default",
|
37
|
+
"Scaling:" => options.scaling ? "yes" : "no",
|
38
|
+
}
|
39
|
+
).each { |s| say " #{s}" }
|
40
|
+
end
|
41
|
+
|
42
|
+
raise RHC::DomainNotFoundException.new("No domains found. Please create a domain with 'rhc domain create <namespace>' before creating applications.") if rest_client.domains.empty?
|
43
|
+
|
44
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
45
|
+
|
46
|
+
# check to make sure the right options are set for enabling jenkins
|
47
|
+
jenkins_rest_app = check_jenkins(name, rest_domain) if options.enable_jenkins
|
48
|
+
|
49
|
+
# create the main app
|
50
|
+
rest_app = create_app(name, cartridge, rest_domain,
|
51
|
+
options.gear_size, options.scaling)
|
52
|
+
|
53
|
+
# create a jenkins app if not available
|
54
|
+
# don't error out if there are issues, setup warnings instead
|
55
|
+
begin
|
56
|
+
jenkins_rest_app = setup_jenkins_app(rest_domain) if options.enable_jenkins and jenkins_rest_app.nil?
|
57
|
+
rescue Exception => e
|
58
|
+
add_issue("Jenkins failed to install - #{e}",
|
59
|
+
"Installing jenkins and jenkins-client",
|
60
|
+
"rhc app create jenkins",
|
61
|
+
"rhc cartridge add jenkins-client -a #{rest_app.name}")
|
62
|
+
end
|
63
|
+
|
64
|
+
if jenkins_rest_app
|
65
|
+
success, attempts, exit_code, exit_message = false, 1, 157, nil
|
66
|
+
while (!success && exit_code == 157 && attempts < MAX_RETRIES)
|
67
|
+
begin
|
68
|
+
setup_jenkins_client(rest_app)
|
69
|
+
success = true
|
70
|
+
rescue RHC::Rest::ServerErrorException => e
|
71
|
+
if (e.code == 157)
|
72
|
+
# error downloading Jenkins /jnlpJars/jenkins-cli.jar
|
73
|
+
attempts += 1
|
74
|
+
debug "Jenkins server could not be contacted, sleep and then retry: attempt #{attempts}\n #{e.message}"
|
75
|
+
sleep(10)
|
76
|
+
end
|
77
|
+
exit_code = e.code
|
78
|
+
exit_message = e.message
|
79
|
+
rescue Exception => e
|
80
|
+
# timeout and other exceptions
|
81
|
+
exit_code = 1
|
82
|
+
exit_message = e.message
|
83
|
+
end
|
84
|
+
end
|
85
|
+
add_issue("Jenkins client failed to install - #{exit_message}",
|
86
|
+
"Install the jenkins client",
|
87
|
+
"rhc cartridge add jenkins-client -a #{rest_app.name}") if !success
|
88
|
+
end
|
89
|
+
|
90
|
+
if options.dns
|
91
|
+
say "Your application's domain name is being propagated worldwide (this might take a minute)..."
|
92
|
+
unless dns_propagated? rest_app.host
|
93
|
+
add_issue("We were unable to lookup your hostname (#{rest_app.host}) in a reasonable amount of time and can not clone your application.",
|
94
|
+
"Clone your git repo",
|
95
|
+
"rhc app git-clone #{rest_app.name}")
|
96
|
+
|
97
|
+
output_issues(rest_app)
|
98
|
+
return 0
|
99
|
+
end
|
100
|
+
|
101
|
+
if options.git
|
102
|
+
begin
|
103
|
+
run_git_clone(rest_app)
|
104
|
+
rescue RHC::GitException => e
|
105
|
+
warn "#{e}"
|
106
|
+
unless RHC::Helpers.windows? and windows_nslookup_bug?(rest_app)
|
107
|
+
add_issue("We were unable to clone your application's git repo - #{e}",
|
108
|
+
"Clone your git repo",
|
109
|
+
"rhc app git-clone #{rest_app.name}")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
display_app(rest_app, rest_app.cartridges, rest_app.scalable_carts.first)
|
116
|
+
|
117
|
+
if issues?
|
118
|
+
output_issues(rest_app)
|
119
|
+
else
|
120
|
+
results {
|
121
|
+
rest_app.messages.each { |msg| say msg }
|
122
|
+
jenkins_rest_app.messages.each { |msg| say msg } if options.enable_jenkins and jenkins_rest_app
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
0
|
127
|
+
end
|
128
|
+
|
129
|
+
summary "Clone and configure an application's repository locally"
|
130
|
+
description "This is a convenience wrapper for 'git clone' with the added",
|
131
|
+
"benefit of adding configuration data such as the application's",
|
132
|
+
"UUID to the local repository. It also automatically",
|
133
|
+
"figures out the git url from the application name so you don't",
|
134
|
+
"have to look it up."
|
135
|
+
syntax "<app> [--namespace namespace]"
|
136
|
+
option ["-n", "--namespace namespace"], "Namespace to add your application to", :context => :namespace_context, :required => true
|
137
|
+
argument :app, "The application you wish to clone", ["-a", "--app name"]
|
138
|
+
# TODO: Implement default values for arguments once ffranz has added context arguments
|
139
|
+
# argument :directory, "The name of a new directory to clone into", [], :default => nil
|
140
|
+
def git_clone(app)
|
141
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
142
|
+
rest_app = rest_domain.find_application(app)
|
143
|
+
run_git_clone(rest_app)
|
144
|
+
0
|
145
|
+
end
|
146
|
+
|
147
|
+
summary "Delete an application from the server"
|
148
|
+
description "Deletes your application and all of its data from the server.",
|
149
|
+
"Use with caution as this operation is permanent."
|
150
|
+
syntax "<app> [--namespace namespace]"
|
151
|
+
option ["-n", "--namespace namespace"], "Namespace to add your application to", :context => :namespace_context, :required => true
|
152
|
+
option ["-b", "--bypass"], "DEPRECATED Please use '--confirm'", :deprecated => {:key => :confirm, :value => true}
|
153
|
+
option ["--confirm"], "Deletes the application without prompting the user"
|
154
|
+
argument :app, "The application you wish to delete", ["-a", "--app name"]
|
155
|
+
alias_action :destroy, :deprecated => true
|
156
|
+
def delete(app)
|
157
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
158
|
+
rest_app = rest_domain.find_application(app)
|
159
|
+
do_delete = true
|
160
|
+
|
161
|
+
do_delete = agree "Are you sure you wish to delete the '#{rest_app.name}' application? (yes/no)" unless options.confirm
|
162
|
+
|
163
|
+
if do_delete
|
164
|
+
paragraph { say "Deleting application '#{rest_app.name}'" }
|
165
|
+
rest_app.destroy
|
166
|
+
results { say "Application '#{rest_app.name}' successfully deleted" }
|
167
|
+
end
|
168
|
+
0
|
169
|
+
end
|
170
|
+
|
171
|
+
summary "Start the application"
|
172
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
173
|
+
argument :app, "The name of the application you are starting", ["-a", "--app app"], :context => :app_context
|
174
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
175
|
+
def start(app)
|
176
|
+
app_action app, :start
|
177
|
+
|
178
|
+
results { say "#{app} started" }
|
179
|
+
0
|
180
|
+
end
|
181
|
+
|
182
|
+
summary "Stop the application"
|
183
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
184
|
+
argument :app, "The name of the application you are stopping", ["-a", "--app app"], :context => :app_context
|
185
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
186
|
+
def stop(app)
|
187
|
+
app_action app, :stop
|
188
|
+
|
189
|
+
results { say "#{app} stopped" }
|
190
|
+
0
|
191
|
+
end
|
192
|
+
|
193
|
+
summary "Stops all application processes"
|
194
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
195
|
+
argument :app, "The name of the application you are stopping", ["-a", "--app app"], :context => :app_context
|
196
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
197
|
+
def force_stop(app)
|
198
|
+
app_action app, :stop, true
|
199
|
+
|
200
|
+
results { say "#{app} force stopped" }
|
201
|
+
0
|
202
|
+
end
|
203
|
+
|
204
|
+
summary "Restart the application"
|
205
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
206
|
+
argument :app, "The name of the application you are restarting", ["-a", "--app app"], :context => :app_context
|
207
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
208
|
+
def restart(app)
|
209
|
+
app_action app, :restart
|
210
|
+
|
211
|
+
results { say "#{app} restarted" }
|
212
|
+
0
|
213
|
+
end
|
214
|
+
|
215
|
+
summary "Reload the application's configuration"
|
216
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
217
|
+
argument :app, "The name of the application you are reloading", ["-a", "--app app"], :context => :app_context
|
218
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
219
|
+
def reload(app)
|
220
|
+
app_action app, :reload
|
221
|
+
|
222
|
+
results { say "#{app} config reloaded" }
|
223
|
+
0
|
224
|
+
end
|
225
|
+
|
226
|
+
summary "Clean out the application's logs and tmp directories and tidy up the git repo on the server"
|
227
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
228
|
+
argument :app, "The name of the application you are tidying", ["-a", "--app app"], :context => :app_context
|
229
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
230
|
+
def tidy(app)
|
231
|
+
app_action app, :tidy
|
232
|
+
|
233
|
+
results { say "#{app} cleaned up" }
|
234
|
+
0
|
235
|
+
end
|
236
|
+
|
237
|
+
summary "Show information about an application"
|
238
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
239
|
+
argument :app, "The name of the application you are getting information on", ["-a", "--app app"], :context => :app_context
|
240
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
241
|
+
option ["--state"], "Get the current state of the application's gears"
|
242
|
+
def show(app)
|
243
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
244
|
+
rest_app = rest_domain.find_application(app)
|
245
|
+
unless options.state
|
246
|
+
display_app(rest_app,rest_app.cartridges,rest_app.scalable_carts.first)
|
247
|
+
else
|
248
|
+
results do
|
249
|
+
rest_app.gear_groups.each do |gg|
|
250
|
+
say "Geargroup #{gg.cartridges.collect { |c| c['name'] }.join('+')} is #{gg.gears.first['state']}"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
0
|
255
|
+
end
|
256
|
+
|
257
|
+
summary "Show status of an application's gears"
|
258
|
+
syntax "<app> [--namespace namespace] [--app app]"
|
259
|
+
argument :app, "The name of the application you are getting information on", ["-a", "--app app"], :context => :app_context
|
260
|
+
option ["-n", "--namespace namespace"], "Namespace of the application the cartridge belongs to", :context => :namespace_context, :required => true
|
261
|
+
deprecated "rhc app show --state"
|
262
|
+
def status(app)
|
263
|
+
# TODO: add a way to deprecate this and alias to show --apache
|
264
|
+
options.state = true
|
265
|
+
show(app)
|
266
|
+
end
|
267
|
+
|
268
|
+
private
|
269
|
+
include RHC::GitHelpers
|
270
|
+
include RHC::CartridgeHelpers
|
271
|
+
|
272
|
+
def app_action(app, action, *args)
|
273
|
+
rest_domain = rest_client.find_domain(options.namespace)
|
274
|
+
rest_app = rest_domain.find_application(app)
|
275
|
+
result = rest_app.send action, *args
|
276
|
+
result
|
277
|
+
end
|
278
|
+
|
279
|
+
def create_app(name, cartridge, rest_domain, gear_size=nil, scale=nil)
|
280
|
+
app_options = {:cartridge => cartridge}
|
281
|
+
app_options[:gear_profile] = gear_size if gear_size
|
282
|
+
app_options[:scale] = scale if scale
|
283
|
+
app_options[:debug] = true if @debug
|
284
|
+
|
285
|
+
debug "Creating application '#{name}' with these options - #{app_options}.inspect"
|
286
|
+
|
287
|
+
rest_cartridge = find_cartridge rest_client, cartridge, "standalone"
|
288
|
+
app_options[:cartridge] = rest_cartridge.name
|
289
|
+
|
290
|
+
rest_app = rest_domain.add_application name, app_options
|
291
|
+
|
292
|
+
debug "'#{rest_app.name}' created"
|
293
|
+
|
294
|
+
rest_app
|
295
|
+
end
|
296
|
+
|
297
|
+
def dns_propagated?(host, sleep_time=2)
|
298
|
+
#
|
299
|
+
# Confirm that the host exists in DNS
|
300
|
+
#
|
301
|
+
debug "Start checking for application dns @ '#{host}'"
|
302
|
+
|
303
|
+
found = false
|
304
|
+
|
305
|
+
# Allow DNS to propagate
|
306
|
+
Kernel.sleep 5
|
307
|
+
|
308
|
+
# Now start checking for DNS
|
309
|
+
for i in 0..MAX_RETRIES-1
|
310
|
+
found = host_exist?(host)
|
311
|
+
break if found
|
312
|
+
|
313
|
+
say " retry # #{i+1} - Waiting for DNS: #{host}"
|
314
|
+
Kernel.sleep sleep_time.to_i
|
315
|
+
sleep_time *= DEFAULT_DELAY_THROTTLE
|
316
|
+
end
|
317
|
+
|
318
|
+
debug "End checking for application dns @ '#{host} - found=#{found}'"
|
319
|
+
|
320
|
+
found
|
321
|
+
end
|
322
|
+
|
323
|
+
def host_exist?(host)
|
324
|
+
# :nocov:
|
325
|
+
dns = Resolv::DNS.new
|
326
|
+
dns.getresources(host, Resolv::DNS::Resource::IN::A).any?
|
327
|
+
# :nocov:
|
328
|
+
end
|
329
|
+
|
330
|
+
def check_sshkeys!
|
331
|
+
wizard = RHC::SSHWizard.new(rest_client)
|
332
|
+
wizard.run
|
333
|
+
end
|
334
|
+
|
335
|
+
def run_git_clone(rest_app)
|
336
|
+
debug "Pulling new repo down"
|
337
|
+
|
338
|
+
check_sshkeys! unless options.noprompt
|
339
|
+
|
340
|
+
repo_dir = options.repo || rest_app.name
|
341
|
+
git_clone_repo rest_app.git_url, repo_dir
|
342
|
+
|
343
|
+
configure_git rest_app
|
344
|
+
|
345
|
+
true
|
346
|
+
end
|
347
|
+
|
348
|
+
def configure_git(rest_app)
|
349
|
+
debug "Configuring git repo"
|
350
|
+
|
351
|
+
repo_dir = options.repo || rest_app.name
|
352
|
+
Dir.chdir(repo_dir) do |dir|
|
353
|
+
git_config_set "rhc.app-uuid", rest_app.uuid
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def jenkins_app_name
|
358
|
+
return "jenkins" if options.enable_jenkins == true or options.enable_jenkins == "true"
|
359
|
+
return options.enable_jenkins if options.enable_jenkins.is_a?(String)
|
360
|
+
nil
|
361
|
+
end
|
362
|
+
|
363
|
+
def check_jenkins(app_name, rest_domain)
|
364
|
+
debug "Checking if jenkins arguments are valid"
|
365
|
+
raise ArgumentError, "The --no-dns option can't be used in conjunction with --enable-jenkins when creating an application. Either remove the --no-dns option or first install your application with --no-dns and then use 'rhc cartridge add' to embed the Jenkins client." unless options.dns
|
366
|
+
|
367
|
+
|
368
|
+
begin
|
369
|
+
jenkins_rest_app = rest_domain.find_application(:framework => "jenkins-1.4")
|
370
|
+
rescue RHC::ApplicationNotFoundException
|
371
|
+
debug "No Jenkins apps found during check"
|
372
|
+
|
373
|
+
# app name and jenkins app name are the same
|
374
|
+
raise ArgumentError, "You have named both your main application and your Jenkins application '#{app_name}'. In order to continue you'll need to specify a different name with --enable-jenkins or choose
|
375
|
+
a different application name." if jenkins_app_name == app_name
|
376
|
+
|
377
|
+
# jenkins app name and existing app are the same
|
378
|
+
begin
|
379
|
+
rest_app = rest_domain.find_application(:name => jenkins_app_name)
|
380
|
+
raise ArgumentError, "You have named your Jenkins application the same as an existing application '#{app_name}'. In order to continue you'll need to specify a different name with --enable-jenkins or delete the current application using 'rhc app delete #{app_name}'"
|
381
|
+
rescue RHC::ApplicationNotFoundException
|
382
|
+
end
|
383
|
+
|
384
|
+
debug "Jenkins arguments valid"
|
385
|
+
return nil
|
386
|
+
end
|
387
|
+
|
388
|
+
say "Found existing Jenkins application: #{jenkins_rest_app.name}"
|
389
|
+
say "Ignoring user specified Jenkins app name : #{options.enable_jenkins}" if jenkins_rest_app.name != options.enable_jenkins and options.enable_jenkins.is_a?(String)
|
390
|
+
|
391
|
+
debug "Jenkins arguments valid"
|
392
|
+
jenkins_rest_app
|
393
|
+
end
|
394
|
+
|
395
|
+
def setup_jenkins_app(rest_domain)
|
396
|
+
debug "Creating a new jenkins application"
|
397
|
+
rest_app = create_app(jenkins_app_name, "jenkins-1.4", rest_domain)
|
398
|
+
|
399
|
+
say "Jenkins domain name is being propagated worldwide (this might take a minute)..."
|
400
|
+
# If we can't get the dns we can't install the client so return nil
|
401
|
+
dns_propagated?(rest_app.host) ? rest_app : nil
|
402
|
+
|
403
|
+
end
|
404
|
+
|
405
|
+
def setup_jenkins_client(rest_app)
|
406
|
+
rest_app.add_cartridge("jenkins-client-1.4", 300)
|
407
|
+
end
|
408
|
+
|
409
|
+
def run_nslookup(host)
|
410
|
+
# :nocov:
|
411
|
+
`nslookup #{host}`
|
412
|
+
$?.exitstatus == 0
|
413
|
+
# :nocov:
|
414
|
+
end
|
415
|
+
|
416
|
+
def run_ping(host)
|
417
|
+
# :nocov:
|
418
|
+
`ping #{host} -n 2`
|
419
|
+
$?.exitstatus == 0
|
420
|
+
# :nocov:
|
421
|
+
end
|
422
|
+
|
423
|
+
def windows_nslookup_bug?(rest_app)
|
424
|
+
windows_nslookup = run_nslookup(rest_app.host)
|
425
|
+
windows_ping = run_ping(rest_app.host)
|
426
|
+
|
427
|
+
if windows_nslookup and !windows_ping # this is related to BZ #826769
|
428
|
+
issue = <<WINSOCKISSUE
|
429
|
+
We were unable to lookup your hostname (#{rest_app.host})
|
430
|
+
in a reasonable amount of time. This can happen periodically and may
|
431
|
+
take up to 10 extra minutes to propagate depending on where you are in the
|
432
|
+
world. This may also be related to an issue with Winsock on Windows [1][2].
|
433
|
+
We recommend you wait a few minutes then clone your git repository manually.
|
434
|
+
|
435
|
+
[1] http://support.microsoft.com/kb/299357
|
436
|
+
[2] http://support.microsoft.com/kb/811259
|
437
|
+
WINSOCKISSUE
|
438
|
+
add_issue(issue,
|
439
|
+
"Clone your git repo",
|
440
|
+
"rhc app git-clone #{rest_app.name}")
|
441
|
+
|
442
|
+
return true
|
443
|
+
end
|
444
|
+
|
445
|
+
false
|
446
|
+
end
|
447
|
+
|
448
|
+
def output_issues(rest_app)
|
449
|
+
reasons, steps = format_issues(4)
|
450
|
+
warn <<WARNING_OUTPUT
|
451
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
452
|
+
WARNING: Your application was created successfully but had problems during
|
453
|
+
configuration. Below is a list of the issues and steps you can
|
454
|
+
take to complete the configuration of your application.
|
455
|
+
|
456
|
+
Application URL: #{rest_app.app_url}
|
457
|
+
|
458
|
+
Issues:
|
459
|
+
#{reasons}
|
460
|
+
Steps to complete your configuration:
|
461
|
+
#{steps}
|
462
|
+
If you can't get your application '#{rest_app.name}' running in the browser,
|
463
|
+
you can try destroying and recreating the application:
|
464
|
+
|
465
|
+
$ rhc app delete #{rest_app.name} --confirm
|
466
|
+
|
467
|
+
If this doesn't work for you, let us know in the forums or in IRC and we'll
|
468
|
+
make sure to get you up and running.
|
469
|
+
|
470
|
+
Forums - https://openshift.redhat.com/community/forums/openshift
|
471
|
+
IRC - #openshift (on Freenode)
|
472
|
+
|
473
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
474
|
+
|
475
|
+
WARNING_OUTPUT
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|