startapp 0.1.11 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/features/app_feature.rb +25 -0
- data/features/core_feature.rb +4 -2
- data/features/members_feature.rb +21 -1
- data/lib/rhc/commands/app.rb +64 -13
- data/lib/rhc/commands/apps.rb +7 -3
- data/lib/rhc/commands/create.rb +2 -1
- data/lib/rhc/commands/domain.rb +2 -1
- data/lib/rhc/commands/member.rb +348 -76
- data/lib/rhc/commands/scp.rb +15 -6
- data/lib/rhc/commands/snapshot.rb +5 -80
- data/lib/rhc/commands/team.rb +103 -0
- data/lib/rhc/context_helper.rb +57 -15
- data/lib/rhc/exceptions.rb +26 -2
- data/lib/rhc/git_helpers.rb +1 -1
- data/lib/rhc/helpers.rb +1 -1
- data/lib/rhc/output_helpers.rb +33 -8
- data/lib/rhc/rest/api.rb +1 -1
- data/lib/rhc/rest/cartridge.rb +6 -1
- data/lib/rhc/rest/client.rb +124 -5
- data/lib/rhc/rest/membership.rb +51 -6
- data/lib/rhc/rest/mock.rb +82 -8
- data/lib/rhc/rest/team.rb +34 -0
- data/lib/rhc/rest.rb +1 -0
- data/lib/rhc/ssh_helpers.rb +88 -0
- data/lib/rhc/usage_templates/command_help.erb +13 -3
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/spec/direct_execution_helper.rb +1 -0
- data/spec/rhc/command_spec.rb +22 -3
- data/spec/rhc/commands/app_spec.rb +81 -3
- data/spec/rhc/commands/apps_spec.rb +41 -1
- data/spec/rhc/commands/domain_spec.rb +1 -1
- data/spec/rhc/commands/member_spec.rb +393 -22
- data/spec/rhc/commands/scp_spec.rb +14 -3
- data/spec/rhc/commands/snapshot_spec.rb +1 -2
- data/spec/rhc/commands/team_spec.rb +191 -0
- data/spec/rhc/helpers_spec.rb +2 -0
- data/spec/rhc/rest_client_spec.rb +23 -0
- data/spec/rhc/rest_spec.rb +5 -5
- data/spec/spec_helper.rb +36 -0
- metadata +8 -2
|
@@ -5,7 +5,7 @@ module RHC::Commands
|
|
|
5
5
|
summary "Save the current state of your application locally"
|
|
6
6
|
syntax "<action>"
|
|
7
7
|
description <<-DESC
|
|
8
|
-
Snapshots allow you to export the current state of your
|
|
8
|
+
Snapshots allow you to export the current state of your StartApp application
|
|
9
9
|
into an archive on your local system, and then to restore it later.
|
|
10
10
|
|
|
11
11
|
The snapshot archive contains the Git repository, dumps of any attached databases,
|
|
@@ -21,49 +21,19 @@ module RHC::Commands
|
|
|
21
21
|
syntax "<application> [--filepath FILE] [--ssh path_to_ssh_executable]"
|
|
22
22
|
takes_application :argument => true
|
|
23
23
|
option ["-f", "--filepath FILE"], "Local path to save tarball (default: ./$APPNAME.tar.gz)"
|
|
24
|
-
option ["--deployment"], "Snapshot as a deployable file which can be deployed with '
|
|
24
|
+
option ["--deployment"], "Snapshot as a deployable file which can be deployed with 'app deploy'"
|
|
25
25
|
option ["--ssh PATH"], "Full path to your SSH executable with additional options"
|
|
26
26
|
alias_action :"app snapshot save", :root_command => true, :deprecated => true
|
|
27
27
|
def save(app)
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
rest_app = find_app
|
|
30
30
|
|
|
31
31
|
raise RHC::DeploymentsNotSupportedException.new if options.deployment && !rest_app.supports?("DEPLOY")
|
|
32
32
|
|
|
33
|
-
ssh_uri = URI.parse(rest_app.ssh_url)
|
|
34
33
|
filename = options.filepath ? options.filepath : "#{rest_app.name}.tar.gz"
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
ssh_cmd = "#{ssh} #{ssh_uri.user}@#{ssh_uri.host} '#{snapshot_cmd}' > #{filename}"
|
|
38
|
-
debug ssh_cmd
|
|
39
|
-
|
|
40
|
-
say "Pulling down a snapshot to #{filename}..."
|
|
35
|
+
save_snapshot(rest_app, filename, options.deployment, options.ssh)
|
|
41
36
|
|
|
42
|
-
begin
|
|
43
|
-
if !RHC::Helpers.windows?
|
|
44
|
-
status, output = exec(ssh_cmd)
|
|
45
|
-
if status != 0
|
|
46
|
-
debug output
|
|
47
|
-
raise RHC::SnapshotSaveException.new "Error in trying to save snapshot. You can try to save manually by running:\n#{ssh_cmd}"
|
|
48
|
-
end
|
|
49
|
-
else
|
|
50
|
-
Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh|
|
|
51
|
-
File.open(filename, 'wb') do |file|
|
|
52
|
-
ssh.exec! "snapshot" do |channel, stream, data|
|
|
53
|
-
if stream == :stdout
|
|
54
|
-
file.write(data)
|
|
55
|
-
else
|
|
56
|
-
debug data
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
|
|
63
|
-
debug e.backtrace
|
|
64
|
-
raise RHC::SnapshotSaveException.new "Error in trying to save snapshot. You can try to save manually by running:\n#{ssh_cmd}"
|
|
65
|
-
end
|
|
66
|
-
results { say "Success" }
|
|
67
37
|
0
|
|
68
38
|
end
|
|
69
39
|
|
|
@@ -74,59 +44,14 @@ module RHC::Commands
|
|
|
74
44
|
option ["--ssh PATH"], "Full path to your SSH executable with additional options"
|
|
75
45
|
alias_action :"app snapshot restore", :root_command => true, :deprecated => true
|
|
76
46
|
def restore(app)
|
|
77
|
-
ssh = check_ssh_executable! options.ssh
|
|
78
47
|
rest_app = find_app
|
|
79
48
|
filename = options.filepath ? options.filepath : "#{rest_app.name}.tar.gz"
|
|
80
49
|
|
|
81
50
|
if File.exists? filename
|
|
82
|
-
|
|
83
|
-
include_git = RHC::Helpers.windows? ? true : RHC::TarGz.contains(filename, './*/git')
|
|
84
|
-
ssh_uri = URI.parse(rest_app.ssh_url)
|
|
85
|
-
|
|
86
|
-
ssh_cmd = "cat '#{filename}' | #{ssh} #{ssh_uri.user}@#{ssh_uri.host} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'"
|
|
87
|
-
|
|
88
|
-
say "Restoring from snapshot #{filename}..."
|
|
89
|
-
debug ssh_cmd
|
|
90
|
-
|
|
91
|
-
begin
|
|
92
|
-
if !RHC::Helpers.windows?
|
|
93
|
-
status, output = exec(ssh_cmd)
|
|
94
|
-
if status != 0
|
|
95
|
-
debug output
|
|
96
|
-
raise RHC::SnapshotRestoreException.new "Error in trying to restore snapshot. You can try to restore manually by running:\n#{ssh_cmd}"
|
|
97
|
-
end
|
|
98
|
-
else
|
|
99
|
-
ssh = Net::SSH.start(ssh_uri.host, ssh_uri.user)
|
|
100
|
-
ssh.open_channel do |channel|
|
|
101
|
-
channel.exec("restore#{include_git ? ' INCLUDE_GIT' : ''}") do |ch, success|
|
|
102
|
-
channel.on_data do |ch, data|
|
|
103
|
-
say data
|
|
104
|
-
end
|
|
105
|
-
channel.on_extended_data do |ch, type, data|
|
|
106
|
-
say data
|
|
107
|
-
end
|
|
108
|
-
channel.on_close do |ch|
|
|
109
|
-
say "Terminating..."
|
|
110
|
-
end
|
|
111
|
-
File.open(filename, 'rb') do |file|
|
|
112
|
-
file.chunk(1024) do |chunk|
|
|
113
|
-
channel.send_data chunk
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
channel.eof!
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
ssh.loop
|
|
120
|
-
end
|
|
121
|
-
rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
|
|
122
|
-
debug e.backtrace
|
|
123
|
-
raise RHC::SnapshotRestoreException.new "Error in trying to restore snapshot. You can try to restore manually by running:\n#{ssh_cmd}"
|
|
124
|
-
end
|
|
125
|
-
|
|
51
|
+
restore_snapshot(rest_app, filename, options.ssh)
|
|
126
52
|
else
|
|
127
53
|
raise RHC::SnapshotRestoreException.new "Archive not found: #{filename}"
|
|
128
54
|
end
|
|
129
|
-
results { say "Success" }
|
|
130
55
|
0
|
|
131
56
|
end
|
|
132
57
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require 'rhc/commands/base'
|
|
2
|
+
|
|
3
|
+
module RHC::Commands
|
|
4
|
+
class Team < Base
|
|
5
|
+
summary "Create or delete a team"
|
|
6
|
+
syntax "<action>"
|
|
7
|
+
description <<-DESC
|
|
8
|
+
People who typically share the same role can be added to a team. The team can
|
|
9
|
+
then be added as a member of a domain, and all of the people in the team will
|
|
10
|
+
inherit the team's role on the domain.
|
|
11
|
+
|
|
12
|
+
If a person is a member of multiple teams which are members of a domain, or
|
|
13
|
+
is also added as a domain member individually, their effective role is the
|
|
14
|
+
higher of their individual role or their teams' roles on the domain.
|
|
15
|
+
|
|
16
|
+
To create a team, run 'app create-team'.
|
|
17
|
+
|
|
18
|
+
To add members to an existing team, use the 'app add-member' command.
|
|
19
|
+
|
|
20
|
+
To list members of an existing team, use the 'app members' command.
|
|
21
|
+
DESC
|
|
22
|
+
default_action :help
|
|
23
|
+
|
|
24
|
+
summary "Create a new team"
|
|
25
|
+
syntax "<team_name>"
|
|
26
|
+
description <<-DESC
|
|
27
|
+
People who typically share the same role can be added to a team. The team can
|
|
28
|
+
then be added as a member of a domain, and all of the people in the team will
|
|
29
|
+
inherit the team's role on the domain.
|
|
30
|
+
|
|
31
|
+
If a person is a member of multiple teams which are members of a domain, or
|
|
32
|
+
is also added as a domain member individually, their effective role is the
|
|
33
|
+
higher of their individual role or their teams' roles on the domain.
|
|
34
|
+
DESC
|
|
35
|
+
argument :team_name, "New team name (min 2 chars, max 250 chars)", ["-t", "--team-name NAME"]
|
|
36
|
+
def create(name)
|
|
37
|
+
say "Creating team '#{name}' ... "
|
|
38
|
+
rest_client.add_team(name)
|
|
39
|
+
success "done"
|
|
40
|
+
|
|
41
|
+
info "You may now add team members using the 'app add-member' command"
|
|
42
|
+
|
|
43
|
+
0
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
summary "Display a team and its members"
|
|
47
|
+
syntax "<team_name>"
|
|
48
|
+
takes_team :argument => true
|
|
49
|
+
def show(_)
|
|
50
|
+
team = find_team
|
|
51
|
+
|
|
52
|
+
display_team(team, true)
|
|
53
|
+
|
|
54
|
+
0
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
summary "Display all teams you are a member of"
|
|
58
|
+
option ['--mine'], "Display only teams you own"
|
|
59
|
+
alias_action :teams, :root_command => true
|
|
60
|
+
def list
|
|
61
|
+
teams = rest_client.send(options.mine ? :owned_teams : :teams, {:include => "members"})
|
|
62
|
+
|
|
63
|
+
teams.each do |t|
|
|
64
|
+
display_team(t, true)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if options.mine
|
|
68
|
+
success "You have #{pluralize(teams.length, 'team')}."
|
|
69
|
+
else
|
|
70
|
+
success "You are a member of #{pluralize(teams.length, 'team')}."
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
0
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
summary "Delete a team"
|
|
77
|
+
syntax "<team_name>"
|
|
78
|
+
takes_team :argument => true
|
|
79
|
+
def delete(_)
|
|
80
|
+
team = find_team(:owned => true)
|
|
81
|
+
|
|
82
|
+
say "Deleting team '#{team.name}' ... "
|
|
83
|
+
team.destroy
|
|
84
|
+
success "deleted"
|
|
85
|
+
|
|
86
|
+
0
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
summary "Leave a team (remove your membership)"
|
|
90
|
+
syntax "<team_name> [-t TEAM_NAME] [--team-id TEAM_ID]"
|
|
91
|
+
takes_team :argument => true
|
|
92
|
+
def leave(_)
|
|
93
|
+
team = find_team
|
|
94
|
+
|
|
95
|
+
say "Leaving team ... "
|
|
96
|
+
result = team.leave
|
|
97
|
+
success "done"
|
|
98
|
+
result.messages.each{ |s| paragraph{ say s } }
|
|
99
|
+
|
|
100
|
+
0
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
data/lib/rhc/context_helper.rb
CHANGED
|
@@ -10,21 +10,43 @@ module RHC
|
|
|
10
10
|
|
|
11
11
|
def self.included(other)
|
|
12
12
|
other.module_eval do
|
|
13
|
+
def self.takes_team(opts={})
|
|
14
|
+
if opts[:argument]
|
|
15
|
+
argument :team_name, "Name of a team", ["-t", "--team-name NAME"], :allow_nil => true, :covered_by => :team_id
|
|
16
|
+
else
|
|
17
|
+
#:nocov:
|
|
18
|
+
option ["-t", "--team-name NAME"], "Name of a team", :covered_by => :team_id
|
|
19
|
+
#:nocov:
|
|
20
|
+
end
|
|
21
|
+
option ["--team-id ID"], "ID of a team", :covered_by => :team_name
|
|
22
|
+
end
|
|
23
|
+
|
|
13
24
|
def self.takes_domain(opts={})
|
|
14
25
|
if opts[:argument]
|
|
15
26
|
argument :namespace, "Name of a domain", ["-n", "--namespace NAME"], :allow_nil => true, :default => :from_local_git
|
|
16
27
|
else
|
|
28
|
+
#:nocov:
|
|
17
29
|
option ["-n", "--namespace NAME"], "Name of a domain", :default => :from_local_git
|
|
30
|
+
#:nocov:
|
|
18
31
|
end
|
|
19
32
|
end
|
|
20
|
-
|
|
21
|
-
def self.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
|
|
34
|
+
def self.takes_membership_container(opts={})
|
|
35
|
+
if opts && opts[:argument]
|
|
36
|
+
if opts && opts[:writable]
|
|
37
|
+
#:nocov:
|
|
38
|
+
argument :namespace, "Name of a domain", ["-n", "--namespace NAME"], :allow_nil => true, :default => :from_local_git
|
|
39
|
+
#:nocov:
|
|
40
|
+
else
|
|
41
|
+
argument :target, "The name of a domain, or an application name with domain (domain or domain/application)", ["--target NAME_OR_PATH"], :allow_nil => true, :covered_by => [:application_id, :namespace, :app]
|
|
42
|
+
end
|
|
26
43
|
end
|
|
44
|
+
option ["-n", "--namespace NAME"], "Name of a domain"
|
|
45
|
+
option ["-a", "--app NAME"], "Name of an application" unless opts && opts[:writable]
|
|
46
|
+
option ["-t", "--team-name NAME"], "Name of a team"
|
|
47
|
+
option ["--team-id ID"], "ID of a team"
|
|
27
48
|
end
|
|
49
|
+
|
|
28
50
|
def self.takes_application(opts={})
|
|
29
51
|
if opts[:argument]
|
|
30
52
|
argument :app, "Name of an application", ["-a", "--app NAME"], :allow_nil => true, :default => :from_local_git, :covered_by => :application_id
|
|
@@ -37,6 +59,18 @@ module RHC
|
|
|
37
59
|
end
|
|
38
60
|
end
|
|
39
61
|
|
|
62
|
+
def find_team(opts={})
|
|
63
|
+
if id = options.team_id.presence
|
|
64
|
+
return rest_client.find_team_by_id(id, opts)
|
|
65
|
+
end
|
|
66
|
+
team_name = (opts && opts[:team_name]) || options.team_name
|
|
67
|
+
if team_name.present?
|
|
68
|
+
rest_client.find_team(team_name, opts)
|
|
69
|
+
else
|
|
70
|
+
raise ArgumentError, "You must specify a team name with -t, or a team id with --team-id."
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
40
74
|
def find_domain(opts={})
|
|
41
75
|
domain = options.namespace || options.target || namespace_context
|
|
42
76
|
if domain
|
|
@@ -46,7 +80,7 @@ module RHC
|
|
|
46
80
|
end
|
|
47
81
|
end
|
|
48
82
|
|
|
49
|
-
def
|
|
83
|
+
def find_membership_container(opts={})
|
|
50
84
|
domain, app =
|
|
51
85
|
if options.target.present?
|
|
52
86
|
options.target.split(/\//)
|
|
@@ -57,32 +91,40 @@ module RHC
|
|
|
57
91
|
[options.namespace || namespace_context, options.app]
|
|
58
92
|
end
|
|
59
93
|
end
|
|
60
|
-
|
|
94
|
+
|
|
95
|
+
if options.team_id.present?
|
|
96
|
+
rest_client.find_team_by_id(options.team_id)
|
|
97
|
+
elsif options.team_name.present?
|
|
98
|
+
rest_client.find_team(options.team_name)
|
|
99
|
+
elsif app && domain
|
|
61
100
|
rest_client.find_application(domain, app)
|
|
62
101
|
elsif domain
|
|
63
102
|
rest_client.find_domain(domain)
|
|
103
|
+
elsif opts && opts[:writable]
|
|
104
|
+
raise ArgumentError, "You must specify a domain with -n, or a team with -t."
|
|
64
105
|
else
|
|
65
|
-
raise ArgumentError, "You must specify a domain with -n,
|
|
106
|
+
raise ArgumentError, "You must specify a domain with -n, an application with -a, or a team with -t."
|
|
66
107
|
end
|
|
67
108
|
end
|
|
68
109
|
|
|
69
110
|
def find_app(opts={})
|
|
70
|
-
if id = options.application_id
|
|
111
|
+
if id = options.application_id.presence
|
|
71
112
|
if opts.delete(:with_gear_groups)
|
|
72
113
|
return rest_client.find_application_by_id_gear_groups(id, opts)
|
|
73
114
|
else
|
|
74
115
|
return rest_client.find_application_by_id(id, opts)
|
|
75
116
|
end
|
|
76
117
|
end
|
|
118
|
+
option = (opts && opts[:app]) || options.app
|
|
77
119
|
domain, app =
|
|
78
|
-
if
|
|
79
|
-
if
|
|
80
|
-
|
|
120
|
+
if option
|
|
121
|
+
if option =~ /\//
|
|
122
|
+
option.split(/\//)
|
|
81
123
|
else
|
|
82
|
-
[options.namespace || namespace_context,
|
|
124
|
+
[options.namespace || namespace_context, option]
|
|
83
125
|
end
|
|
84
126
|
end
|
|
85
|
-
if app && domain
|
|
127
|
+
if app.present? && domain.present?
|
|
86
128
|
if opts.delete(:with_gear_groups)
|
|
87
129
|
rest_client.find_application_gear_groups(domain, app, opts)
|
|
88
130
|
else
|
data/lib/rhc/exceptions.rb
CHANGED
|
@@ -67,6 +67,24 @@ module RHC
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
class TeamsNotSupportedException < Exception
|
|
71
|
+
def initialize(message="Server does not support teams")
|
|
72
|
+
super message, 161
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class TeamNotFoundException < Exception
|
|
77
|
+
def initialize(message="Team not found")
|
|
78
|
+
super message, 162
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class MemberNotFoundException < Exception
|
|
83
|
+
def initialize(message="Member not found")
|
|
84
|
+
super message, 163
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
70
88
|
class GitPermissionDenied < GitException; end
|
|
71
89
|
class GitDirectoryExists < GitException; end
|
|
72
90
|
|
|
@@ -138,6 +156,12 @@ module RHC
|
|
|
138
156
|
end
|
|
139
157
|
end
|
|
140
158
|
|
|
159
|
+
class AppCloneNotSupportedException < Exception
|
|
160
|
+
def initialize(message="The server does not support cloning apps")
|
|
161
|
+
super message, 134
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
141
165
|
class MissingScalingValueException < Exception
|
|
142
166
|
def initialize(message="Must provide either a min or max value for scaling")
|
|
143
167
|
super message
|
|
@@ -190,13 +214,13 @@ module RHC
|
|
|
190
214
|
end
|
|
191
215
|
|
|
192
216
|
class ChangeMembersOnResourceNotSupported < Exception
|
|
193
|
-
def initialize(message="You can only add or remove members on a domain.")
|
|
217
|
+
def initialize(message="You can only add or remove members on a domain or team.")
|
|
194
218
|
super message, 1
|
|
195
219
|
end
|
|
196
220
|
end
|
|
197
221
|
|
|
198
222
|
class MembersNotSupported < Exception
|
|
199
|
-
def initialize(message="The server does not support adding or removing members.")
|
|
223
|
+
def initialize(message="The server does not support adding or removing members on this resource.")
|
|
200
224
|
super message, 1
|
|
201
225
|
end
|
|
202
226
|
end
|
data/lib/rhc/git_helpers.rb
CHANGED
|
@@ -60,7 +60,7 @@ module RHC
|
|
|
60
60
|
# :nocov: These all call external binaries so test them in cucumber
|
|
61
61
|
def git_config_get(key)
|
|
62
62
|
return nil unless has_git?
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
config_get_cmd = "#{git_cmd} config --get #{key}"
|
|
65
65
|
value = %x[#{config_get_cmd}].strip
|
|
66
66
|
debug "Git config '#{config_get_cmd}' returned '#{value}'"
|
data/lib/rhc/helpers.rb
CHANGED
data/lib/rhc/output_helpers.rb
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
module RHC
|
|
2
2
|
module OutputHelpers
|
|
3
3
|
|
|
4
|
+
def display_team(team, ids=false)
|
|
5
|
+
paragraph do
|
|
6
|
+
header ["Team #{team.name}", ("(owned by #{team.owner})" if team.owner.present?)] do
|
|
7
|
+
section(:bottom => 1) do
|
|
8
|
+
say format_table \
|
|
9
|
+
nil,
|
|
10
|
+
get_properties(
|
|
11
|
+
team,
|
|
12
|
+
(:id if ids),
|
|
13
|
+
(:global if team.global?),
|
|
14
|
+
:compact_members
|
|
15
|
+
),
|
|
16
|
+
:delete => true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
4
22
|
def display_domain(domain, applications=nil, ids=false)
|
|
5
23
|
paragraph do
|
|
6
24
|
header ["Domain #{domain.name}", ("(owned by #{domain.owner})" if domain.owner.present?)] do
|
|
@@ -26,7 +44,7 @@ module RHC
|
|
|
26
44
|
#---------------------------
|
|
27
45
|
# Application information
|
|
28
46
|
#---------------------------
|
|
29
|
-
def display_app(app, cartridges=nil, properties=nil)
|
|
47
|
+
def display_app(app, cartridges=nil, properties=nil, verbose=false)
|
|
30
48
|
paragraph do
|
|
31
49
|
header [app.name, "@ #{app.app_url}", "(uuid: #{app.uuid})"] do
|
|
32
50
|
section(:bottom => 1) do
|
|
@@ -43,7 +61,7 @@ module RHC
|
|
|
43
61
|
:aliases]),
|
|
44
62
|
:delete => true
|
|
45
63
|
end
|
|
46
|
-
cartridges.each{ |c| section(:bottom => 1){ display_cart(c) } } if cartridges
|
|
64
|
+
cartridges.each{ |c| section(:bottom => 1){ display_cart(c, verbose ? :verbose : []) } } if cartridges
|
|
47
65
|
end
|
|
48
66
|
end
|
|
49
67
|
end
|
|
@@ -69,6 +87,8 @@ module RHC
|
|
|
69
87
|
format_scaling_info(cart.scaling)
|
|
70
88
|
elsif cart.shares_gears?
|
|
71
89
|
"Located with #{cart.collocated_with.join(", ")}"
|
|
90
|
+
elsif cart.external? && cart.current_scale == 0
|
|
91
|
+
"none (external service)"
|
|
72
92
|
else
|
|
73
93
|
"%d %s" % [format_value(:current_scale, cart.current_scale), format_value(:gear_profile, cart.gear_profile)]
|
|
74
94
|
end
|
|
@@ -84,13 +104,18 @@ module RHC
|
|
|
84
104
|
#---------------------------
|
|
85
105
|
|
|
86
106
|
def display_cart(cart, *properties)
|
|
107
|
+
verbose = properties.delete(:verbose)
|
|
87
108
|
say format_table \
|
|
88
109
|
format_cart_header(cart),
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
get_properties(cart, *properties).
|
|
111
|
+
concat(verbose && cart.custom? ? [[:description, cart.description.strip]] : []).
|
|
112
|
+
concat([[:downloaded_cartridge_url, cart.url]]).
|
|
113
|
+
concat(verbose && cart.custom? ? [[:version, cart.version]] : []).
|
|
114
|
+
concat(verbose && cart.custom? && cart.license.strip.downcase != 'unknown' ? [[:license, cart.license]] : []).
|
|
115
|
+
concat(cart.custom? ? [[:website, cart.website]] : []).
|
|
116
|
+
concat([[cart.scalable? ? :scaling : :gears, format_cart_gears(cart)]]).
|
|
117
|
+
concat(cart.properties.map{ |p| ["#{table_heading(p['name'])}:", p['value']] }.sort{ |a,b| a[0] <=> b[0] }).
|
|
118
|
+
concat(cart.environment_variables.present? ? [[:environment_variables, cart.environment_variables.map{|item| "#{item[:name]}=#{item[:value]}" }.sort.join(', ')]] : []),
|
|
94
119
|
:delete => true
|
|
95
120
|
|
|
96
121
|
say format_usage_message(cart) if cart.usage_rate?
|
|
@@ -248,7 +273,7 @@ module RHC
|
|
|
248
273
|
when :activations
|
|
249
274
|
value.collect{|item| date(item.created_at.to_s)}.join("\n")
|
|
250
275
|
when :auto_deploy
|
|
251
|
-
value ? 'auto (on git push)' : "manual (use '
|
|
276
|
+
value ? 'auto (on git push)' : "manual (use 'app deploy')"
|
|
252
277
|
else
|
|
253
278
|
case value
|
|
254
279
|
when Array then value.empty? ? '<none>' : value.join(', ')
|
data/lib/rhc/rest/api.rb
CHANGED
|
@@ -67,7 +67,7 @@ module RHC
|
|
|
67
67
|
if !api_version_match?
|
|
68
68
|
warn "WARNING: API version mismatch. This client supports #{client_api_versions.join(', ')} but
|
|
69
69
|
server at #{URI.parse(client.url).host} supports #{@server_api_versions.join(', ')}."
|
|
70
|
-
warn "The client version may be outdated; please consider updating '
|
|
70
|
+
warn "The client version may be outdated; please consider updating 'app'. We will continue, but you may encounter problems."
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
data/lib/rhc/rest/cartridge.rb
CHANGED
|
@@ -5,7 +5,8 @@ module RHC
|
|
|
5
5
|
|
|
6
6
|
define_attr :type, :name, :display_name, :properties, :gear_profile, :status_messages, :scales_to, :scales_from, :scales_with,
|
|
7
7
|
:current_scale, :supported_scales_to, :supported_scales_from, :tags, :description, :collocated_with, :base_gear_storage,
|
|
8
|
-
:additional_gear_storage, :url, :environment_variables, :gear_size, :automatic_updates
|
|
8
|
+
:additional_gear_storage, :url, :environment_variables, :gear_size, :automatic_updates,
|
|
9
|
+
:version, :license, :website, :description
|
|
9
10
|
|
|
10
11
|
def scalable?
|
|
11
12
|
supported_scales_to != supported_scales_from
|
|
@@ -31,6 +32,10 @@ module RHC
|
|
|
31
32
|
v
|
|
32
33
|
end
|
|
33
34
|
|
|
35
|
+
def external?
|
|
36
|
+
tags.include?('external')
|
|
37
|
+
end
|
|
38
|
+
|
|
34
39
|
def shares_gears?
|
|
35
40
|
Array(collocated_with).present?
|
|
36
41
|
end
|