startapp 0.1.6

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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -0,0 +1,260 @@
1
+ module RHC
2
+ module OutputHelpers
3
+
4
+ def display_domain(domain, applications=nil, ids=false)
5
+ paragraph do
6
+ header ["Domain #{domain.name}", ("(owned by #{domain.owner})" if domain.owner.present?)] do
7
+ section(:bottom => 1) do
8
+ say format_table \
9
+ nil,
10
+ get_properties(
11
+ domain,
12
+ :creation_time,
13
+ (:id if ids),
14
+ (:allowed_gear_sizes unless domain.allowed_gear_sizes.nil?),
15
+ :compact_members
16
+ ),
17
+ :delete => true
18
+ end
19
+ applications.each do |a|
20
+ display_app(a,a.cartridges)
21
+ end if applications.present?
22
+ end
23
+ end
24
+ end
25
+
26
+ #---------------------------
27
+ # Application information
28
+ #---------------------------
29
+ def display_app(app, cartridges=nil, properties=nil)
30
+ paragraph do
31
+ header [app.name, "@ #{app.app_url}", "(uuid: #{app.uuid})"] do
32
+ section(:bottom => 1) do
33
+ say format_table \
34
+ nil,
35
+ get_properties(app, properties ||
36
+ [:domain,
37
+ :creation_time,
38
+ :gear_info,
39
+ :git_url,
40
+ :initial_git_url,
41
+ :ssh_string,
42
+ :auto_deploy,
43
+ :aliases]),
44
+ :delete => true
45
+ end
46
+ cartridges.each{ |c| section(:bottom => 1){ display_cart(c) } } if cartridges
47
+ end
48
+ end
49
+ end
50
+
51
+ def display_app_configurations(rest_app)
52
+ display_app(rest_app, nil, [:auto_deploy, :keep_deployments, :deployment_type, :deployment_branch])
53
+ end
54
+
55
+ def format_cart_header(cart)
56
+ [
57
+ cart.name,
58
+ cart.name != cart.display_name ? "(#{cart.display_name})" : nil,
59
+ ].compact
60
+ end
61
+
62
+ def format_scaling_info(scaling)
63
+ "x%d (minimum: %s, maximum: %s) on %s gears" %
64
+ [:current_scale, :scales_from, :scales_to, :gear_profile].map{ |key| format_value(key, scaling[key]) } if scaling
65
+ end
66
+
67
+ def format_cart_gears(cart)
68
+ if cart.scalable?
69
+ format_scaling_info(cart.scaling)
70
+ elsif cart.shares_gears?
71
+ "Located with #{cart.collocated_with.join(", ")}"
72
+ else
73
+ "%d %s" % [format_value(:current_scale, cart.current_scale), format_value(:gear_profile, cart.gear_profile)]
74
+ end
75
+ end
76
+
77
+ def format_gear_info(info)
78
+ "%d (defaults to %s)" %
79
+ [:gear_count, :gear_profile].map{ |key| format_value(key, info[key]) } if info
80
+ end
81
+
82
+ #---------------------------
83
+ # Cartridge information
84
+ #---------------------------
85
+
86
+ def display_cart(cart, *properties)
87
+ say format_table \
88
+ format_cart_header(cart),
89
+ get_properties(cart, *properties).
90
+ concat([[:downloaded_cartridge_url, cart.url]]).
91
+ concat([[cart.scalable? ? :scaling : :gears, format_cart_gears(cart)]]).
92
+ concat(cart.properties.map{ |p| ["#{table_heading(p['name'])}:", p['value']] }.sort{ |a,b| a[0] <=> b[0] }).
93
+ concat(cart.environment_variables.present? ? [[:environment_variables, cart.environment_variables.map{|item| "#{item[:name]}=#{item[:value]}" }.sort.join(', ')]] : []),
94
+ :delete => true
95
+
96
+ say format_usage_message(cart) if cart.usage_rate?
97
+ end
98
+
99
+ def display_key(key, *properties)
100
+ properties = [:fingerprint, :principal, :visible_to_ssh?] if properties.empty?
101
+ say format_table(
102
+ properties.include?(:name) ? nil : format_key_header(key),
103
+ get_properties(key, *properties),
104
+ {
105
+ :delete => true,
106
+ :color => (:green if properties.include?(:visible_to_ssh?) && key.visible_to_ssh?),
107
+ }
108
+ )
109
+ end
110
+
111
+ def display_authorization(auth, default=nil)
112
+ say format_table(
113
+ auth.note || "<no description>",
114
+ get_properties(auth, :token, :scopes, :creation_time, :expires_in_seconds),
115
+ {
116
+ :delete => true,
117
+ :color => (:green if auth.token == default),
118
+ }
119
+ )
120
+ end
121
+
122
+ def format_key_header(key)
123
+ [
124
+ key.name,
125
+ "(type: #{key.type})",
126
+ ].compact
127
+ end
128
+
129
+ def display_cart_storage_info(cart, title="Storage Info")
130
+ say format_table \
131
+ title,
132
+ get_properties(cart,:base_gear_storage,:additional_gear_storage)
133
+ end
134
+
135
+ def display_cart_storage_list(carts)
136
+ carts.each{ |cart| paragraph{ display_cart_storage_info(cart, cart.display_name) } }
137
+ end
138
+
139
+ def format_usage_message(cart)
140
+ "This gear costs an additional $#{cart.usage_rate} per gear after the first 3 gears."
141
+ end
142
+
143
+ def default_display_env_var(env_var_name, env_var_value=nil)
144
+ info "#{env_var_name}#{env_var_value.nil? ? '' : '=' + env_var_value}"
145
+ end
146
+
147
+ def display_env_var_list(env_vars, opts={})
148
+ if env_vars.present?
149
+ if opts[:table]
150
+ say table(env_vars.collect{ |item| [item.name, opts[:quotes] ? "\"#{item.value}\"" : item.value] }, :header => ['Name', 'Value'])
151
+ else
152
+ env_vars.sort.each do |env_var|
153
+ default_display_env_var(env_var.name, opts[:quotes] ? "\"#{env_var.value}\"" : env_var.value)
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ def display_deployment(item, highlight_active=true)
160
+ deployment = item[:deployment]
161
+ active = item[:active]
162
+ paragraph do
163
+ say format_table(
164
+ "Deployment ID #{deployment.id} #{active ? '(active)' : '(inactive)'}",
165
+ get_properties(deployment, :ref, :sha1, :created_at, :artifact_url, :hot_deploy, :force_clean_build, :activations),
166
+ {
167
+ :delete => true,
168
+ :color => (:green if active && highlight_active)
169
+ }
170
+ )
171
+ end
172
+ end
173
+
174
+ def display_deployment_list(deployment_activations, highlight_active=true)
175
+ if deployment_activations.present?
176
+ paragraph do
177
+ deployment_activations.each do |item|
178
+ activation = item[:activation]
179
+ deployment = item[:deployment]
180
+ rollback = item[:rollback]
181
+ rollback_to = item[:rollback_to]
182
+ rolled_back = item[:rolled_back]
183
+ active = item[:active]
184
+ say color(
185
+ date(activation.created_at.to_s) +
186
+ ', deployment ' + deployment.id +
187
+ (rollback ? " (rollback to #{date(rollback_to.to_s)}#{rolled_back ? ', rolled back' : ''})" : rolled_back ? ' (rolled back)' : ''),
188
+ active ? :green : rolled_back ? :yellow : nil)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ private
195
+ def format_table(heading,values,opts = {})
196
+ values = values.to_a if values.is_a? Hash
197
+ values.delete_if do |arr|
198
+ arr[0] = "#{table_heading(arr.first)}:" if arr[0].is_a? Symbol
199
+ opts[:delete] and arr.last.nil? || arr.last == ""
200
+ end
201
+
202
+ table(values, :heading => heading, :indent => heading ? ' ' : nil, :color => opts[:color])
203
+ end
204
+
205
+ def format_no_info(type)
206
+ ["This #{type} has no information to show"]
207
+ end
208
+
209
+
210
+ # This uses the array of properties to retrieve them from an object
211
+ def get_properties(object,*properties)
212
+ properties.flatten.map do |prop|
213
+ # Either send the property to the object or yield it
214
+ next if prop.nil?
215
+ value = begin
216
+ block_given? ? yield(prop) : object.send(prop)
217
+ rescue ::Exception => e
218
+ debug_error(e)
219
+ "<error>"
220
+ end
221
+ [prop, format_value(prop,value)]
222
+ end.compact
223
+ end
224
+
225
+ # Format some special values
226
+ def format_value(prop,value)
227
+ case prop
228
+ when :plan_id
229
+ case value
230
+ when 'free' then 'Free'
231
+ when 'silver' then 'Silver'
232
+ else value && value.capitalize || nil
233
+ end
234
+ when :visible_to_ssh?
235
+ value || nil
236
+ when :creation_time, :created_at
237
+ date(value)
238
+ when :scales_from,:scales_to
239
+ (value == -1 ? "available" : value)
240
+ when :gear_info
241
+ format_gear_info(value)
242
+ when :base_gear_storage,:additional_gear_storage
243
+ ((value.nil? or value == 0) ? "None" : "#{value}GB")
244
+ when :aliases
245
+ value.kind_of?(Array) ? value.join(', ') : value
246
+ when :expires_in_seconds
247
+ distance_of_time_in_words(value)
248
+ when :activations
249
+ value.collect{|item| date(item.created_at.to_s)}.join("\n")
250
+ when :auto_deploy
251
+ value ? 'auto (on git push)' : "manual (use 'rhc deploy')"
252
+ else
253
+ case value
254
+ when Array then value.empty? ? '<none>' : value.join(', ')
255
+ else value
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,11 @@
1
+ module RHC
2
+ module Rest
3
+ class Activation < Base
4
+ define_attr :created_at
5
+
6
+ def <=>(other)
7
+ other.created_at <=> created_at
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ module RHC
2
+ module Rest
3
+ class Alias < Base
4
+
5
+ define_attr :id, :has_private_ssl_certificate, :certificate_added_at
6
+
7
+ def has_private_ssl_certificate?
8
+ has_private_ssl_certificate
9
+ end
10
+
11
+ def destroy
12
+ debug "Deleting alias #{self.id}"
13
+ rest_method :delete
14
+ end
15
+ alias :delete :destroy
16
+
17
+ def add_certificate(ssl_certificate_content, private_key_content, pass_phrase)
18
+ debug "Running add_certificate for alias #{@id}"
19
+ raise RHC::Rest::SslCertificatesNotSupported, "The server does not support SSL certificates for custom aliases." unless supports? :update
20
+ foo = rest_method :update, {
21
+ :ssl_certificate => ssl_certificate_content,
22
+ :private_key => private_key_content,
23
+ :pass_phrase => pass_phrase
24
+ }
25
+ end
26
+
27
+ def delete_certificate
28
+ debug "Running delete_certificate for alias #{@id}"
29
+ raise RHC::Rest::SslCertificatesNotSupported, "The server does not support SSL certificates for custom aliases." unless supports? :update
30
+ rest_method :update, {}
31
+ end
32
+
33
+ def <=>(a)
34
+ return self.name <=> a.name
35
+ end
36
+
37
+ def to_s
38
+ self.id
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,87 @@
1
+ module RHC
2
+ module Rest
3
+ class Api < Base
4
+ attr_reader :server_api_versions, :client_api_versions
5
+
6
+ def initialize(client, preferred_api_versions=[])
7
+ super(nil, client)
8
+
9
+ # API version negotiation
10
+ @server_api_versions = []
11
+ debug "Client supports API versions #{preferred_api_versions.join(', ')}"
12
+ @client_api_versions = preferred_api_versions
13
+ @server_api_versions, @current_api_version, links = api_info({
14
+ :url => client.url,
15
+ :method => :get,
16
+ :accept => :json,
17
+ :lazy_auth => true,
18
+ })
19
+ debug "Server supports API versions #{@server_api_versions.join(', ')}"
20
+
21
+ if api_version_negotiated
22
+ debug " Using API version #{api_version_negotiated}"
23
+ unless client_api_version_current?
24
+ debug "Client API version #{api_version_negotiated} is not current. Refetching API"
25
+ # need to re-fetch API
26
+ @server_api_versions, @current_api_version, links = api_info({
27
+ :url => client.url,
28
+ :method => :get,
29
+ :accept => :json,
30
+ :api_version => api_version_negotiated,
31
+ :lazy_auth => true,
32
+ })
33
+ end
34
+ else
35
+ warn_about_api_versions
36
+ end
37
+
38
+ attributes['links'] = links
39
+
40
+ rescue RHC::Rest::ResourceNotFoundException => e
41
+ raise ApiEndpointNotFound.new(
42
+ "The OpenShift server is not responding correctly. Check "\
43
+ "that '#{client.url}' is the correct URL for your server. "\
44
+ "The server may be offline or misconfigured.")
45
+ end
46
+
47
+ ### API version related methods
48
+ def api_version_match?
49
+ ! api_version_negotiated.nil?
50
+ end
51
+
52
+ # return the API version that the server and this client can agree on
53
+ def api_version_negotiated
54
+ client_api_versions.reverse. # choose the last API version listed
55
+ detect { |v| @server_api_versions.include? v }
56
+ end
57
+
58
+ def client_api_version_current?
59
+ current_api_version == api_version_negotiated
60
+ end
61
+
62
+ def current_api_version
63
+ @current_api_version
64
+ end
65
+
66
+ def warn_about_api_versions
67
+ if !api_version_match?
68
+ warn "WARNING: API version mismatch. This client supports #{client_api_versions.join(', ')} but
69
+ server at #{URI.parse(client.url).host} supports #{@server_api_versions.join(', ')}."
70
+ warn "The client version may be outdated; please consider updating 'rhc'. We will continue, but you may encounter problems."
71
+ end
72
+ end
73
+
74
+ protected
75
+ include RHC::Helpers
76
+
77
+ private
78
+ # execute +req+ with RestClient, and return [server_api_versions, links]
79
+ def api_info(req)
80
+ client.request(req) do |response|
81
+ json_response = ::RHC::Json.decode(response.content)
82
+ [ json_response['supported_api_versions'], json_response['api_version'] || json_response['version'].to_f, json_response['data'] ]
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end