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.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/autocomplete/rhc_bash +1672 -0
- data/bin/app +37 -0
- data/conf/express.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +191 -0
- data/features/deployments_feature.rb +129 -0
- data/features/domains_feature.rb +58 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +166 -0
- data/lib/rhc/auth/basic.rb +64 -0
- data/lib/rhc/auth/token.rb +102 -0
- data/lib/rhc/auth/token_store.rb +53 -0
- data/lib/rhc/auth.rb +5 -0
- data/lib/rhc/autocomplete.rb +66 -0
- data/lib/rhc/autocomplete_templates/bash.erb +39 -0
- data/lib/rhc/cartridge_helpers.rb +118 -0
- data/lib/rhc/cli.rb +40 -0
- data/lib/rhc/command_runner.rb +185 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +726 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +115 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +329 -0
- data/lib/rhc/commands/clone.rb +66 -0
- data/lib/rhc/commands/configure.rb +20 -0
- data/lib/rhc/commands/create.rb +100 -0
- data/lib/rhc/commands/delete.rb +19 -0
- data/lib/rhc/commands/deploy.rb +32 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +172 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/force_stop.rb +17 -0
- data/lib/rhc/commands/git_clone.rb +34 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/logs.rb +21 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/reload.rb +17 -0
- data/lib/rhc/commands/restart.rb +17 -0
- data/lib/rhc/commands/scp.rb +54 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/show.rb +43 -0
- data/lib/rhc/commands/snapshot.rb +137 -0
- data/lib/rhc/commands/ssh.rb +51 -0
- data/lib/rhc/commands/sshkey.rb +97 -0
- data/lib/rhc/commands/start.rb +17 -0
- data/lib/rhc/commands/stop.rb +17 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands/tidy.rb +17 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +321 -0
- data/lib/rhc/context_helper.rb +121 -0
- data/lib/rhc/core_ext.rb +202 -0
- data/lib/rhc/coverage_helper.rb +33 -0
- data/lib/rhc/deployment_helpers.rb +111 -0
- data/lib/rhc/exceptions.rb +256 -0
- data/lib/rhc/git_helpers.rb +106 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +481 -0
- data/lib/rhc/highline_extensions.rb +479 -0
- data/lib/rhc/json.rb +51 -0
- data/lib/rhc/output_helpers.rb +260 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/alias.rb +42 -0
- data/lib/rhc/rest/api.rb +87 -0
- data/lib/rhc/rest/application.rb +348 -0
- data/lib/rhc/rest/attributes.rb +36 -0
- data/lib/rhc/rest/authorization.rb +8 -0
- data/lib/rhc/rest/base.rb +79 -0
- data/lib/rhc/rest/cartridge.rb +162 -0
- data/lib/rhc/rest/client.rb +650 -0
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/domain.rb +98 -0
- data/lib/rhc/rest/environment_variable.rb +15 -0
- data/lib/rhc/rest/gear_group.rb +16 -0
- data/lib/rhc/rest/httpclient.rb +145 -0
- data/lib/rhc/rest/key.rb +44 -0
- data/lib/rhc/rest/membership.rb +105 -0
- data/lib/rhc/rest/mock.rb +1042 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/scp_helpers.rb +27 -0
- data/lib/rhc/ssh_helpers.rb +380 -0
- data/lib/rhc/tar_gz.rb +51 -0
- data/lib/rhc/usage_templates/command_help.erb +51 -0
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/lib/rhc/usage_templates/help.erb +61 -0
- data/lib/rhc/usage_templates/missing_help.erb +1 -0
- data/lib/rhc/usage_templates/options_help.erb +12 -0
- data/lib/rhc/vendor/okjson.rb +600 -0
- data/lib/rhc/vendor/parseconfig.rb +178 -0
- data/lib/rhc/vendor/sshkey.rb +253 -0
- data/lib/rhc/vendor/zliby.rb +628 -0
- data/lib/rhc/version.rb +5 -0
- data/lib/rhc/wizard.rb +637 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +82 -0
- data/spec/direct_execution_helper.rb +339 -0
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +31 -0
- data/spec/rhc/assets/cert.crt +22 -0
- data/spec/rhc/assets/cert_key_rsa +27 -0
- data/spec/rhc/assets/empty.txt +0 -0
- data/spec/rhc/assets/env_vars.txt +7 -0
- data/spec/rhc/assets/env_vars_2.txt +1 -0
- data/spec/rhc/assets/foo.txt +1 -0
- data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
- data/spec/rhc/assets/targz_sample.tar.gz +0 -0
- data/spec/rhc/auth_spec.rb +442 -0
- data/spec/rhc/cli_spec.rb +186 -0
- data/spec/rhc/command_spec.rb +435 -0
- data/spec/rhc/commands/account_spec.rb +42 -0
- data/spec/rhc/commands/alias_spec.rb +333 -0
- data/spec/rhc/commands/app_spec.rb +777 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +157 -0
- data/spec/rhc/commands/cartridge_spec.rb +665 -0
- data/spec/rhc/commands/clone_spec.rb +41 -0
- data/spec/rhc/commands/deployment_spec.rb +327 -0
- data/spec/rhc/commands/domain_spec.rb +401 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +102 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +247 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/scp_spec.rb +77 -0
- data/spec/rhc/commands/server_spec.rb +69 -0
- data/spec/rhc/commands/setup_spec.rb +118 -0
- data/spec/rhc/commands/snapshot_spec.rb +179 -0
- data/spec/rhc/commands/ssh_spec.rb +163 -0
- data/spec/rhc/commands/sshkey_spec.rb +188 -0
- data/spec/rhc/commands/tail_spec.rb +81 -0
- data/spec/rhc/commands/threaddump_spec.rb +84 -0
- data/spec/rhc/config_spec.rb +407 -0
- data/spec/rhc/helpers_spec.rb +531 -0
- data/spec/rhc/highline_extensions_spec.rb +314 -0
- data/spec/rhc/json_spec.rb +30 -0
- data/spec/rhc/rest_application_spec.rb +258 -0
- data/spec/rhc/rest_client_spec.rb +752 -0
- data/spec/rhc/rest_spec.rb +740 -0
- data/spec/rhc/targz_spec.rb +55 -0
- data/spec/rhc/wizard_spec.rb +756 -0
- data/spec/spec_helper.rb +575 -0
- data/spec/wizard_spec_helper.rb +330 -0
- metadata +469 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'rhc/git_helpers'
|
|
2
|
+
|
|
3
|
+
module RHC
|
|
4
|
+
#
|
|
5
|
+
# Methods in this module should not attempt to read from the options hash
|
|
6
|
+
# in a recursive manner (server_context can't read options.server).
|
|
7
|
+
#
|
|
8
|
+
module ContextHelpers
|
|
9
|
+
include RHC::GitHelpers
|
|
10
|
+
|
|
11
|
+
def self.included(other)
|
|
12
|
+
other.module_eval do
|
|
13
|
+
def self.takes_domain(opts={})
|
|
14
|
+
if opts[:argument]
|
|
15
|
+
argument :namespace, "Name of a domain", ["-n", "--namespace NAME"], :allow_nil => true, :default => :from_local_git
|
|
16
|
+
else
|
|
17
|
+
option ["-n", "--namespace NAME"], "Name of a domain", :default => :from_local_git
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
# Does not take defaults to avoid conflicts
|
|
21
|
+
def self.takes_application_or_domain(opts={})
|
|
22
|
+
option ["-n", "--namespace NAME"], "Name of a domain"
|
|
23
|
+
option ["-a", "--app NAME"], "Name of an application"
|
|
24
|
+
if opts[:argument]
|
|
25
|
+
argument :target, "The name of a domain, or an application name with domain (domain or domain/application)", ["-t", "--target NAME_OR_PATH"], :allow_nil => true, :covered_by => [:application_id, :namespace, :app]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
def self.takes_application(opts={})
|
|
29
|
+
if opts[:argument]
|
|
30
|
+
argument :app, "Name of an application", ["-a", "--app NAME"], :allow_nil => true, :default => :from_local_git, :covered_by => :application_id
|
|
31
|
+
else
|
|
32
|
+
option ["-a", "--app NAME"], "Name of an application", :default => :from_local_git, :covered_by => :application_id
|
|
33
|
+
end
|
|
34
|
+
option ["-n", "--namespace NAME"], "Name of a domain", :default => :from_local_git
|
|
35
|
+
option ["--application-id ID"], "ID of an application", :hide => true, :default => :from_local_git, :covered_by => :app
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def find_domain(opts={})
|
|
41
|
+
domain = options.namespace || options.target || namespace_context
|
|
42
|
+
if domain
|
|
43
|
+
rest_client.find_domain(domain)
|
|
44
|
+
else
|
|
45
|
+
raise ArgumentError, "You must specify a domain with -n."
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def find_app_or_domain(opts={})
|
|
50
|
+
domain, app =
|
|
51
|
+
if options.target.present?
|
|
52
|
+
options.target.split(/\//)
|
|
53
|
+
elsif options.namespace || options.app
|
|
54
|
+
if options.app =~ /\//
|
|
55
|
+
options.app.split(/\//)
|
|
56
|
+
else
|
|
57
|
+
[options.namespace || namespace_context, options.app]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
if app && domain
|
|
61
|
+
rest_client.find_application(domain, app)
|
|
62
|
+
elsif domain
|
|
63
|
+
rest_client.find_domain(domain)
|
|
64
|
+
else
|
|
65
|
+
raise ArgumentError, "You must specify a domain with -n, or an application with -a."
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def find_app(opts={})
|
|
70
|
+
if id = options.application_id
|
|
71
|
+
if opts.delete(:with_gear_groups)
|
|
72
|
+
return rest_client.find_application_by_id_gear_groups(id, opts)
|
|
73
|
+
else
|
|
74
|
+
return rest_client.find_application_by_id(id, opts)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
domain, app =
|
|
78
|
+
if options.app
|
|
79
|
+
if options.app =~ /\//
|
|
80
|
+
options.app.split(/\//)
|
|
81
|
+
else
|
|
82
|
+
[options.namespace || namespace_context, options.app]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
if app && domain
|
|
86
|
+
if opts.delete(:with_gear_groups)
|
|
87
|
+
rest_client.find_application_gear_groups(domain, app, opts)
|
|
88
|
+
else
|
|
89
|
+
rest_client.find_application(domain, app, opts)
|
|
90
|
+
end
|
|
91
|
+
else
|
|
92
|
+
raise ArgumentError, "You must specify an application with -a, or run this command from within Git directory cloned from StartApp."
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def server_context(defaults=nil, arg=nil)
|
|
97
|
+
value = ENV['LIBRA_SERVER'] || (!options.clean && config['libra_server']) || "broker.startapp.bg"
|
|
98
|
+
defaults[arg] = value if defaults && arg
|
|
99
|
+
value
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def from_local_git(defaults, arg)
|
|
103
|
+
@local_git_config ||= {
|
|
104
|
+
:application_id => git_config_get('rhc.app-id').presence,
|
|
105
|
+
:app => git_config_get('rhc.app-name').presence,
|
|
106
|
+
:namespace => git_config_get('rhc.domain-name').presence,
|
|
107
|
+
}
|
|
108
|
+
defaults[arg] ||= @local_git_config[arg] unless @local_git_config[arg].nil?
|
|
109
|
+
@local_git_config
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def namespace_context
|
|
113
|
+
# right now we don't have any logic since we only support one domain
|
|
114
|
+
# TODO: add domain lookup based on uuid
|
|
115
|
+
domain = rest_client.domains.first
|
|
116
|
+
raise RHC::NoDomainsForUser if domain.nil?
|
|
117
|
+
|
|
118
|
+
domain.name
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
data/lib/rhc/core_ext.rb
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# From Rails core_ext/object.rb
|
|
2
|
+
require 'rhc/json'
|
|
3
|
+
require 'open-uri'
|
|
4
|
+
require 'httpclient'
|
|
5
|
+
|
|
6
|
+
class Object
|
|
7
|
+
def present?
|
|
8
|
+
!blank?
|
|
9
|
+
end
|
|
10
|
+
def blank?
|
|
11
|
+
respond_to?(:empty?) ? empty? : !self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def presence
|
|
15
|
+
present? ? self : nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Avoid a conflict if to_json is already defined
|
|
19
|
+
unless Object.new.respond_to? :to_json
|
|
20
|
+
def to_json(options=nil)
|
|
21
|
+
RHC::Json.encode(self)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Array
|
|
27
|
+
# From rails
|
|
28
|
+
def split(value = nil)
|
|
29
|
+
using_block = block_given?
|
|
30
|
+
|
|
31
|
+
inject([[]]) do |results, element|
|
|
32
|
+
if (using_block && yield(element)) || (value == element)
|
|
33
|
+
results << []
|
|
34
|
+
else
|
|
35
|
+
results.last << element
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
results
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class File
|
|
44
|
+
def chunk(chunk_size=1024)
|
|
45
|
+
yield read(chunk_size) until eof?
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class String
|
|
50
|
+
# Wrap string by the given length, and join it with the given character.
|
|
51
|
+
# The method doesn't distinguish between words, it will only work based on
|
|
52
|
+
# the length.
|
|
53
|
+
def wrap(wrap_length=80, char="\n")
|
|
54
|
+
scan(/.{#{wrap_length}}|.+/).join(char)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def strip_heredoc
|
|
58
|
+
indent = scan(/^[ \t]*(?=\S)/).min.size || 0
|
|
59
|
+
gsub(/^[ \t]{#{indent}}/, '').
|
|
60
|
+
gsub(/(\b|\S)[^\S\n]*\n(\S)/m, '\1 \2').
|
|
61
|
+
gsub(/\n+\Z/, '').
|
|
62
|
+
gsub(/\n{3,}/, "\n\n")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
ANSI_ESCAPE_SEQUENCE = /\e\[(\d{1,2}(?:;\d{1,2})*[@-~])/
|
|
66
|
+
ANSI_ESCAPE_MATCH = '\e\[\d+(?:;\d+)*[@-~]'
|
|
67
|
+
CHAR_SKIP_ANSI = "(?:(?:#{ANSI_ESCAPE_MATCH})+.?|.(?:#{ANSI_ESCAPE_MATCH})*)"
|
|
68
|
+
|
|
69
|
+
#
|
|
70
|
+
# Split the given string at limit, treating ANSI escape sequences as
|
|
71
|
+
# zero characters in length. Will insert an ANSI reset code (\e[0m)
|
|
72
|
+
# at the end of each line containing an ANSI code, assuming that a
|
|
73
|
+
# reset was not in the wrapped segment.
|
|
74
|
+
#
|
|
75
|
+
# All newlines are preserved.
|
|
76
|
+
#
|
|
77
|
+
# Lines longer than limit without natural breaks will be forcibly
|
|
78
|
+
# split at the exact limit boundary.
|
|
79
|
+
#
|
|
80
|
+
# Returns an Array
|
|
81
|
+
#
|
|
82
|
+
def textwrap_ansi(limit, breakword=true)
|
|
83
|
+
re = breakword ? /
|
|
84
|
+
(
|
|
85
|
+
# Match substrings that end in whitespace shorter than limit
|
|
86
|
+
#{CHAR_SKIP_ANSI}{1,#{limit}} # up to limit
|
|
87
|
+
(?:\s+|$) # require the limit to end on whitespace
|
|
88
|
+
|
|
|
89
|
+
# Match substrings equal to the limit
|
|
90
|
+
#{CHAR_SKIP_ANSI}{1,#{limit}}
|
|
91
|
+
)
|
|
92
|
+
/x :
|
|
93
|
+
/
|
|
94
|
+
(
|
|
95
|
+
# Match substrings that end in whitespace shorter than limit
|
|
96
|
+
#{CHAR_SKIP_ANSI}{1,#{limit}}
|
|
97
|
+
(?:\s|$) # require the limit to end on whitespace
|
|
98
|
+
|
|
|
99
|
+
# Match all continguous whitespace strings
|
|
100
|
+
#{CHAR_SKIP_ANSI}+?
|
|
101
|
+
(?:\s|$)
|
|
102
|
+
(?:\s+|$)?
|
|
103
|
+
)
|
|
104
|
+
/x
|
|
105
|
+
escapes = []
|
|
106
|
+
|
|
107
|
+
split("\n",-1).inject([]) do |a, line|
|
|
108
|
+
if line.length < limit
|
|
109
|
+
a << line
|
|
110
|
+
else
|
|
111
|
+
line.scan(re) do |segment, other|
|
|
112
|
+
if escapes.present?
|
|
113
|
+
a << escapes.map{ |s| "\e[#{s}"}.join
|
|
114
|
+
a[-1] << segment.rstrip
|
|
115
|
+
else
|
|
116
|
+
a << segment.rstrip
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
segment.scan(ANSI_ESCAPE_SEQUENCE).map{ |e| e.first }.each do |e|
|
|
120
|
+
case e
|
|
121
|
+
when '0m' then escapes.clear
|
|
122
|
+
else escapes << e
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
a[-1] << "\e[0m" if escapes.present?
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
a
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def strip_ansi
|
|
133
|
+
gsub(ANSI_ESCAPE_SEQUENCE, '')
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
unless HTTP::Message.method_defined? :ok?
|
|
138
|
+
#:nocov:
|
|
139
|
+
class HTTP::Message
|
|
140
|
+
def ok?
|
|
141
|
+
HTTP::Status.successful?(status)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
#:nocov:
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
unless DateTime.method_defined? :to_time
|
|
148
|
+
#:nocov:
|
|
149
|
+
class DateTime
|
|
150
|
+
def to_time
|
|
151
|
+
Time.parse(to_s)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
#:nocov:
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
#
|
|
158
|
+
# Allow http => https redirection, see
|
|
159
|
+
# http://bugs.ruby-lang.org/issues/859 to 1.8.7 for rough
|
|
160
|
+
# outline of change.
|
|
161
|
+
#
|
|
162
|
+
module OpenURI
|
|
163
|
+
def self.redirectable?(uri1, uri2) # :nodoc:
|
|
164
|
+
# This test is intended to forbid a redirection from http://... to
|
|
165
|
+
# file:///etc/passwd.
|
|
166
|
+
# However this is ad hoc. It should be extensible/configurable.
|
|
167
|
+
uri1.scheme.downcase == uri2.scheme.downcase ||
|
|
168
|
+
(/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:https?|ftp)\z/i =~ uri2.scheme)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
class Hash
|
|
173
|
+
def stringify_keys!
|
|
174
|
+
keys.each do |key|
|
|
175
|
+
v = delete(key)
|
|
176
|
+
if v.is_a? Hash
|
|
177
|
+
v.stringify_keys!
|
|
178
|
+
elsif v.is_a? Array
|
|
179
|
+
v.each{ |value| value.stringify_keys! if value.is_a? Hash }
|
|
180
|
+
end
|
|
181
|
+
self[(key.to_s rescue key) || key] = v
|
|
182
|
+
end
|
|
183
|
+
self
|
|
184
|
+
end
|
|
185
|
+
def slice!(*args)
|
|
186
|
+
s = []
|
|
187
|
+
args.inject([]) do |a, k|
|
|
188
|
+
s << [k, delete(k)] if has_key?(k)
|
|
189
|
+
end
|
|
190
|
+
s
|
|
191
|
+
end
|
|
192
|
+
def slice(*args)
|
|
193
|
+
args.inject({}) do |h, k|
|
|
194
|
+
h[k] = self[k] if has_key?(k)
|
|
195
|
+
h
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
def reverse_merge!(other_hash)
|
|
199
|
+
# right wins if there is no left
|
|
200
|
+
merge!( other_hash ){|key,left,right| left }
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Must be the first module imported at entry points (executables that run
|
|
2
|
+
# in seperate processes from the test harness) otherwise coverage will be
|
|
3
|
+
# incomplete
|
|
4
|
+
|
|
5
|
+
if RUBY_VERSION >= '1.9' and ENV['RHC_FEATURE_COVERAGE']
|
|
6
|
+
require 'simplecov'
|
|
7
|
+
SimpleCov.start do
|
|
8
|
+
coverage_dir 'coverage/features/'
|
|
9
|
+
command_name 'Integration Tests'
|
|
10
|
+
|
|
11
|
+
# Filters - these files will be ignored.
|
|
12
|
+
add_filter 'lib/rhc/vendor/' # vendored files should be taken directly and only
|
|
13
|
+
# namespaces changed
|
|
14
|
+
add_filter 'features/' # Don't report on the files that run the cucumber tests
|
|
15
|
+
add_filter 'lib/rhc-feature-coverage-helper.rb'
|
|
16
|
+
add_filter 'spec/' # Don't report on the files that run the spec tests
|
|
17
|
+
|
|
18
|
+
# Groups - general categories of test areas
|
|
19
|
+
add_group('Commands') { |src_file| src_file.filename.include?(File.join(%w[lib rhc commands])) }
|
|
20
|
+
add_group('RHC Lib') { |src_file| src_file.filename.include?(File.join(%w[lib rhc])) }
|
|
21
|
+
add_group('REST') { |src_file| src_file.filename.include?(File.join(%w[lib rhc/rest])) }
|
|
22
|
+
add_group('Test') { |src_file| src_file.filename.include?(File.join(%w[features])) or
|
|
23
|
+
src_file.filename.include?(File.join(%w[spec])) }
|
|
24
|
+
|
|
25
|
+
use_merging = true
|
|
26
|
+
# Note, the #:nocov: coverage exclusion should only be used on external functions
|
|
27
|
+
# that cannot be nondestructively tested in a developer environment.
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# suppress output
|
|
31
|
+
SimpleCov.at_exit do
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'rhc/ssh_helpers'
|
|
2
|
+
|
|
3
|
+
module RHC
|
|
4
|
+
module DeploymentHelpers
|
|
5
|
+
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
include RHC::SSHHelpers
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
def deploy_artifact(rest_app, artifact, hot_deploy, force_clean_build)
|
|
13
|
+
is_file = File.file?(artifact)
|
|
14
|
+
is_url = URI::ABS_URI.match(artifact).present?
|
|
15
|
+
|
|
16
|
+
if rest_app.deployment_type == 'binary'
|
|
17
|
+
if is_file
|
|
18
|
+
deploy_local_file(rest_app, artifact, hot_deploy, force_clean_build)
|
|
19
|
+
elsif is_url
|
|
20
|
+
deploy_file_from_url(rest_app, artifact, hot_deploy, force_clean_build)
|
|
21
|
+
else
|
|
22
|
+
paragraph do
|
|
23
|
+
warn "The application '#{rest_app.name}' is configured for binary deployments but the artifact "\
|
|
24
|
+
"provided ('#{artifact}') is not a binary file. Please provide the path to a deployable file on "\
|
|
25
|
+
"your local filesystem or a url, or configure your app to deploy from a git reference with 'rhc "\
|
|
26
|
+
"configure-app #{rest_app.name} --deployment-type git'."
|
|
27
|
+
end
|
|
28
|
+
raise IncompatibleDeploymentTypeException
|
|
29
|
+
end
|
|
30
|
+
elsif is_file || is_url
|
|
31
|
+
paragraph do
|
|
32
|
+
warn "The application '#{rest_app.name}' is configured for git "\
|
|
33
|
+
"reference deployments but the artifact provided ('#{artifact}') is #{is_file ? 'a file' : 'a url'}. Please "\
|
|
34
|
+
"provide a git reference to deploy (branch, tag or commit SHA1) or configure your app to deploy from binaries "\
|
|
35
|
+
"with 'rhc configure-app #{rest_app.name} --deployment-type binary'."
|
|
36
|
+
end
|
|
37
|
+
raise IncompatibleDeploymentTypeException
|
|
38
|
+
else
|
|
39
|
+
deploy_git_ref(rest_app, artifact, hot_deploy, force_clean_build)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def deploy_git_ref(rest_app, ref, hot_deploy, force_clean_build)
|
|
44
|
+
say "Deployment of git ref '#{ref}' in progress for application #{rest_app.name} ..."
|
|
45
|
+
|
|
46
|
+
ssh_url = URI(rest_app.ssh_url)
|
|
47
|
+
remote_cmd = "gear deploy #{ref}#{hot_deploy ? ' --hot-deploy' : ''}#{force_clean_build ? ' --force-clean-build' : ''}"
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
ssh_ruby(ssh_url.host, ssh_url.user, remote_cmd)
|
|
51
|
+
success "Success"
|
|
52
|
+
rescue
|
|
53
|
+
ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
|
|
54
|
+
warn "Error deploying git ref. You can try to deploy manually with:\n#{ssh_cmd}"
|
|
55
|
+
raise
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def deploy_local_file(rest_app, filename, hot_deploy, force_clean_build)
|
|
60
|
+
filename = File.expand_path(filename)
|
|
61
|
+
say "Deployment of file '#{filename}' in progress for application #{rest_app.name} ..."
|
|
62
|
+
|
|
63
|
+
ssh_url = URI(rest_app.ssh_url)
|
|
64
|
+
remote_cmd = "oo-binary-deploy#{hot_deploy ? ' --hot-deploy' : ''}#{force_clean_build ? ' --force-clean-build' : ''}"
|
|
65
|
+
|
|
66
|
+
begin
|
|
67
|
+
ssh_send_file_ruby(ssh_url.host, ssh_url.user, remote_cmd, filename)
|
|
68
|
+
success "Success"
|
|
69
|
+
rescue
|
|
70
|
+
ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
|
|
71
|
+
warn "Error deploying local file. You can try to deploy manually with:\n#{ssh_cmd}"
|
|
72
|
+
raise
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def deploy_file_from_url(rest_app, file_url, hot_deploy, force_clean_build)
|
|
77
|
+
say "Deployment of file '#{file_url}' in progress for application #{rest_app.name} ..."
|
|
78
|
+
|
|
79
|
+
ssh_url = URI(rest_app.ssh_url)
|
|
80
|
+
file_url = URI(file_url)
|
|
81
|
+
|
|
82
|
+
remote_cmd = "oo-binary-deploy#{hot_deploy ? ' --hot-deploy' : ''}#{force_clean_build ? ' --force-clean-build' : ''}"
|
|
83
|
+
|
|
84
|
+
begin
|
|
85
|
+
ssh_send_url_ruby(ssh_url.host, ssh_url.user, remote_cmd, file_url)
|
|
86
|
+
success "Success"
|
|
87
|
+
rescue
|
|
88
|
+
ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
|
|
89
|
+
warn "Error deploying file from url. You can try to deploy manually with:\n#{ssh_cmd}"
|
|
90
|
+
raise
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def activate_deployment(rest_app, deployment_id)
|
|
95
|
+
say "Activating deployment '#{deployment_id}' on application #{rest_app.name} ..."
|
|
96
|
+
|
|
97
|
+
ssh_url = URI(rest_app.ssh_url)
|
|
98
|
+
remote_cmd = "gear activate --all #{deployment_id}"
|
|
99
|
+
|
|
100
|
+
begin
|
|
101
|
+
ssh_ruby(ssh_url.host, ssh_url.user, remote_cmd)
|
|
102
|
+
success "Success"
|
|
103
|
+
rescue
|
|
104
|
+
ssh_cmd = "ssh -t #{ssh_url.user}@#{ssh_url.host} '#{remote_cmd}'"
|
|
105
|
+
warn "Error activating deployment. You can try to activate manually with:\n#{ssh_cmd}"
|
|
106
|
+
raise
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
end
|