azuki 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +71 -0
- data/bin/azuki +17 -0
- data/data/cacert.pem +3988 -0
- data/lib/azuki.rb +17 -0
- data/lib/azuki/auth.rb +339 -0
- data/lib/azuki/cli.rb +38 -0
- data/lib/azuki/client.rb +764 -0
- data/lib/azuki/client/azuki_postgresql.rb +141 -0
- data/lib/azuki/client/cisaurus.rb +26 -0
- data/lib/azuki/client/pgbackups.rb +113 -0
- data/lib/azuki/client/rendezvous.rb +108 -0
- data/lib/azuki/client/ssl_endpoint.rb +25 -0
- data/lib/azuki/command.rb +294 -0
- data/lib/azuki/command/account.rb +23 -0
- data/lib/azuki/command/accounts.rb +34 -0
- data/lib/azuki/command/addons.rb +305 -0
- data/lib/azuki/command/apps.rb +393 -0
- data/lib/azuki/command/auth.rb +86 -0
- data/lib/azuki/command/base.rb +230 -0
- data/lib/azuki/command/certs.rb +209 -0
- data/lib/azuki/command/config.rb +137 -0
- data/lib/azuki/command/db.rb +218 -0
- data/lib/azuki/command/domains.rb +85 -0
- data/lib/azuki/command/drains.rb +46 -0
- data/lib/azuki/command/fork.rb +164 -0
- data/lib/azuki/command/git.rb +64 -0
- data/lib/azuki/command/help.rb +179 -0
- data/lib/azuki/command/keys.rb +115 -0
- data/lib/azuki/command/labs.rb +147 -0
- data/lib/azuki/command/logs.rb +45 -0
- data/lib/azuki/command/maintenance.rb +61 -0
- data/lib/azuki/command/pg.rb +269 -0
- data/lib/azuki/command/pgbackups.rb +329 -0
- data/lib/azuki/command/plugins.rb +110 -0
- data/lib/azuki/command/ps.rb +232 -0
- data/lib/azuki/command/regions.rb +22 -0
- data/lib/azuki/command/releases.rb +124 -0
- data/lib/azuki/command/run.rb +180 -0
- data/lib/azuki/command/sharing.rb +89 -0
- data/lib/azuki/command/ssl.rb +43 -0
- data/lib/azuki/command/stack.rb +62 -0
- data/lib/azuki/command/status.rb +51 -0
- data/lib/azuki/command/update.rb +47 -0
- data/lib/azuki/command/version.rb +23 -0
- data/lib/azuki/deprecated.rb +5 -0
- data/lib/azuki/deprecated/help.rb +38 -0
- data/lib/azuki/distribution.rb +9 -0
- data/lib/azuki/excon.rb +9 -0
- data/lib/azuki/helpers.rb +517 -0
- data/lib/azuki/helpers/azuki_postgresql.rb +165 -0
- data/lib/azuki/helpers/log_displayer.rb +70 -0
- data/lib/azuki/plugin.rb +163 -0
- data/lib/azuki/updater.rb +171 -0
- data/lib/azuki/version.rb +3 -0
- data/lib/vendor/azuki/okjson.rb +598 -0
- data/spec/azuki/auth_spec.rb +256 -0
- data/spec/azuki/client/azuki_postgresql_spec.rb +71 -0
- data/spec/azuki/client/pgbackups_spec.rb +43 -0
- data/spec/azuki/client/rendezvous_spec.rb +62 -0
- data/spec/azuki/client/ssl_endpoint_spec.rb +48 -0
- data/spec/azuki/client_spec.rb +564 -0
- data/spec/azuki/command/addons_spec.rb +601 -0
- data/spec/azuki/command/apps_spec.rb +351 -0
- data/spec/azuki/command/auth_spec.rb +38 -0
- data/spec/azuki/command/base_spec.rb +109 -0
- data/spec/azuki/command/certs_spec.rb +178 -0
- data/spec/azuki/command/config_spec.rb +144 -0
- data/spec/azuki/command/db_spec.rb +110 -0
- data/spec/azuki/command/domains_spec.rb +87 -0
- data/spec/azuki/command/drains_spec.rb +34 -0
- data/spec/azuki/command/fork_spec.rb +56 -0
- data/spec/azuki/command/git_spec.rb +144 -0
- data/spec/azuki/command/help_spec.rb +93 -0
- data/spec/azuki/command/keys_spec.rb +120 -0
- data/spec/azuki/command/labs_spec.rb +100 -0
- data/spec/azuki/command/logs_spec.rb +60 -0
- data/spec/azuki/command/maintenance_spec.rb +51 -0
- data/spec/azuki/command/pg_spec.rb +236 -0
- data/spec/azuki/command/pgbackups_spec.rb +307 -0
- data/spec/azuki/command/plugins_spec.rb +104 -0
- data/spec/azuki/command/ps_spec.rb +195 -0
- data/spec/azuki/command/releases_spec.rb +130 -0
- data/spec/azuki/command/run_spec.rb +83 -0
- data/spec/azuki/command/sharing_spec.rb +59 -0
- data/spec/azuki/command/stack_spec.rb +46 -0
- data/spec/azuki/command/status_spec.rb +48 -0
- data/spec/azuki/command/version_spec.rb +16 -0
- data/spec/azuki/command_spec.rb +211 -0
- data/spec/azuki/helpers/azuki_postgresql_spec.rb +155 -0
- data/spec/azuki/helpers_spec.rb +48 -0
- data/spec/azuki/plugin_spec.rb +172 -0
- data/spec/azuki/updater_spec.rb +44 -0
- data/spec/helper/legacy_help.rb +16 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +224 -0
- data/spec/support/display_message_matcher.rb +49 -0
- data/spec/support/openssl_mock_helper.rb +8 -0
- metadata +211 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
require "azuki/command/base"
|
2
|
+
|
3
|
+
# manage optional features
|
4
|
+
#
|
5
|
+
class Azuki::Command::Labs < Azuki::Command::Base
|
6
|
+
|
7
|
+
# labs
|
8
|
+
#
|
9
|
+
# list experimental features
|
10
|
+
#
|
11
|
+
#Example:
|
12
|
+
#
|
13
|
+
# === User Features (david@azukiapp.com)
|
14
|
+
# [+] dashboard Use Azuki Dashboard by default
|
15
|
+
#
|
16
|
+
# === App Features (glacial-retreat-5913)
|
17
|
+
# [ ] preboot Provide seamless web dyno deploys
|
18
|
+
# [ ] user-env-compile Add user config vars to the environment during slug compilation # $ azuki labs -a example
|
19
|
+
#
|
20
|
+
def index
|
21
|
+
validate_arguments!
|
22
|
+
|
23
|
+
user_features, app_features = api.get_features(app).body.sort_by do |feature|
|
24
|
+
feature["name"]
|
25
|
+
end.partition do |feature|
|
26
|
+
feature["kind"] == "user"
|
27
|
+
end
|
28
|
+
|
29
|
+
display_app = app || "no app specified"
|
30
|
+
|
31
|
+
styled_header "User Features (#{Azuki::Auth.user})"
|
32
|
+
display_features user_features
|
33
|
+
display
|
34
|
+
styled_header "App Features (#{display_app})"
|
35
|
+
display_features app_features
|
36
|
+
end
|
37
|
+
|
38
|
+
alias_command "labs:list", "labs"
|
39
|
+
|
40
|
+
# labs:info FEATURE
|
41
|
+
#
|
42
|
+
# displays additional information about FEATURE
|
43
|
+
#
|
44
|
+
#Example:
|
45
|
+
#
|
46
|
+
# $ azuki labs:info user_env_compile
|
47
|
+
# === user_env_compile
|
48
|
+
# Docs: http://devcenter.azukiapp.com/articles/labs-user-env-compile
|
49
|
+
# Summary: Add user config vars to the environment during slug compilation
|
50
|
+
#
|
51
|
+
def info
|
52
|
+
unless feature_name = shift_argument
|
53
|
+
error("Usage: azuki labs:info FEATURE\nMust specify FEATURE for info.")
|
54
|
+
end
|
55
|
+
validate_arguments!
|
56
|
+
|
57
|
+
feature_data = api.get_feature(feature_name, app).body
|
58
|
+
styled_header(feature_data['name'])
|
59
|
+
styled_hash({
|
60
|
+
'Summary' => feature_data['summary'],
|
61
|
+
'Docs' => feature_data['docs']
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
# labs:disable FEATURE
|
66
|
+
#
|
67
|
+
# disables an experimental feature
|
68
|
+
#
|
69
|
+
#Example:
|
70
|
+
#
|
71
|
+
# $ azuki labs:disable ninja-power
|
72
|
+
# Disabling ninja-power feature for me@example.org... done
|
73
|
+
#
|
74
|
+
def disable
|
75
|
+
feature_name = shift_argument
|
76
|
+
error "Usage: azuki labs:disable FEATURE\nMust specify FEATURE to disable." unless feature_name
|
77
|
+
validate_arguments!
|
78
|
+
|
79
|
+
feature = api.get_features(app).body.detect { |f| f["name"] == feature_name }
|
80
|
+
message = "Disabling #{feature_name} "
|
81
|
+
|
82
|
+
error "No such feature: #{feature_name}" unless feature
|
83
|
+
|
84
|
+
if feature["kind"] == "user"
|
85
|
+
message += "for #{Azuki::Auth.user}"
|
86
|
+
else
|
87
|
+
error "Must specify an app" unless app
|
88
|
+
message += "for #{app}"
|
89
|
+
end
|
90
|
+
|
91
|
+
action message do
|
92
|
+
api.delete_feature feature_name, app
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# labs:enable FEATURE
|
97
|
+
#
|
98
|
+
# enables an experimental feature
|
99
|
+
#
|
100
|
+
#Example:
|
101
|
+
#
|
102
|
+
# $ azuki labs:enable ninja-power
|
103
|
+
# Enabling ninja-power feature for me@example.org... done
|
104
|
+
#
|
105
|
+
def enable
|
106
|
+
feature_name = shift_argument
|
107
|
+
error "Usage: azuki labs:enable FEATURE\nMust specify FEATURE to enable." unless feature_name
|
108
|
+
validate_arguments!
|
109
|
+
|
110
|
+
feature = api.get_features.body.detect { |f| f["name"] == feature_name }
|
111
|
+
message = "Enabling #{feature_name} "
|
112
|
+
|
113
|
+
error "No such feature: #{feature_name}" unless feature
|
114
|
+
|
115
|
+
if feature["kind"] == "user"
|
116
|
+
message += "for #{Azuki::Auth.user}"
|
117
|
+
else
|
118
|
+
error "Must specify an app" unless app
|
119
|
+
message += "for #{app}"
|
120
|
+
end
|
121
|
+
|
122
|
+
feature_data = action(message) do
|
123
|
+
api.post_feature(feature_name, app).body
|
124
|
+
end
|
125
|
+
|
126
|
+
display "WARNING: This feature is experimental and may change or be removed without notice."
|
127
|
+
display "For more information see: #{feature_data["docs"]}" if feature_data["docs"]
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
# app is not required for these commands, so rescue if there is none
|
133
|
+
def app
|
134
|
+
super
|
135
|
+
rescue Azuki::Command::CommandFailed
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
|
139
|
+
def display_features(features)
|
140
|
+
longest_name = features.map { |f| f["name"].to_s.length }.sort.last
|
141
|
+
features.each do |feature|
|
142
|
+
toggle = feature["enabled"] ? "[+]" : "[ ]"
|
143
|
+
display "%s %-#{longest_name}s %s" % [ toggle, feature["name"], feature["summary"] ]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "azuki/command/base"
|
2
|
+
require "azuki/helpers/log_displayer"
|
3
|
+
|
4
|
+
# display logs for an app
|
5
|
+
#
|
6
|
+
class Azuki::Command::Logs < Azuki::Command::Base
|
7
|
+
|
8
|
+
# logs
|
9
|
+
#
|
10
|
+
# display recent log output
|
11
|
+
#
|
12
|
+
# -n, --num NUM # the number of lines to display
|
13
|
+
# -p, --ps PS # only display logs from the given process
|
14
|
+
# -s, --source SOURCE # only display logs from the given source
|
15
|
+
# -t, --tail # continually stream logs
|
16
|
+
#
|
17
|
+
#Example:
|
18
|
+
#
|
19
|
+
# $ azuki logs
|
20
|
+
# 2012-01-01T12:00:00+00:00 azuki[api]: Config add EXAMPLE by email@example.com
|
21
|
+
# 2012-01-01T12:00:01+00:00 azuki[api]: Release v1 created by email@example.com
|
22
|
+
#
|
23
|
+
def index
|
24
|
+
validate_arguments!
|
25
|
+
|
26
|
+
opts = []
|
27
|
+
opts << "tail=1" if options[:tail]
|
28
|
+
opts << "num=#{options[:num]}" if options[:num]
|
29
|
+
opts << "ps=#{URI.encode(options[:ps])}" if options[:ps]
|
30
|
+
opts << "source=#{URI.encode(options[:source])}" if options[:source]
|
31
|
+
|
32
|
+
log_displayer = ::Azuki::Helpers::LogDisplayer.new(azuki, app, opts)
|
33
|
+
log_displayer.display_logs
|
34
|
+
end
|
35
|
+
|
36
|
+
# logs:drains
|
37
|
+
#
|
38
|
+
# DEPRECATED: use `azuki drains`
|
39
|
+
#
|
40
|
+
def drains
|
41
|
+
# deprecation notice added 09/30/2011
|
42
|
+
display("~ `azuki logs:drains` has been deprecated and replaced with `azuki drains`")
|
43
|
+
Azuki::Command::Drains.new.index
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "azuki/command/base"
|
2
|
+
|
3
|
+
# manage maintenance mode for an app
|
4
|
+
#
|
5
|
+
class Azuki::Command::Maintenance < Azuki::Command::Base
|
6
|
+
|
7
|
+
# maintenance
|
8
|
+
#
|
9
|
+
# display the current maintenance status of app
|
10
|
+
#
|
11
|
+
#Example:
|
12
|
+
#
|
13
|
+
# $ azuki maintenance
|
14
|
+
# off
|
15
|
+
#
|
16
|
+
def index
|
17
|
+
validate_arguments!
|
18
|
+
|
19
|
+
case api.get_app_maintenance(app).body['maintenance']
|
20
|
+
when true
|
21
|
+
display('on')
|
22
|
+
when false
|
23
|
+
display('off')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# maintenance:on
|
28
|
+
#
|
29
|
+
# put the app into maintenance mode
|
30
|
+
#
|
31
|
+
#Example:
|
32
|
+
#
|
33
|
+
# $ azuki maintenance:on
|
34
|
+
# Enabling maintenance mode for example
|
35
|
+
#
|
36
|
+
def on
|
37
|
+
validate_arguments!
|
38
|
+
|
39
|
+
action("Enabling maintenance mode for #{app}") do
|
40
|
+
api.post_app_maintenance(app, '1')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# maintenance:off
|
45
|
+
#
|
46
|
+
# take the app out of maintenance mode
|
47
|
+
#
|
48
|
+
#Example:
|
49
|
+
#
|
50
|
+
# $ azuki maintenance:off
|
51
|
+
# Disabling maintenance mode for example
|
52
|
+
#
|
53
|
+
def off
|
54
|
+
validate_arguments!
|
55
|
+
|
56
|
+
action("Disabling maintenance mode for #{app}") do
|
57
|
+
api.post_app_maintenance(app, '0')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require "azuki/client/azuki_postgresql"
|
2
|
+
require "azuki/command/base"
|
3
|
+
require "azuki/helpers/azuki_postgresql"
|
4
|
+
|
5
|
+
# manage azuki-postgresql databases
|
6
|
+
#
|
7
|
+
class Azuki::Command::Pg < Azuki::Command::Base
|
8
|
+
|
9
|
+
include Azuki::Helpers::AzukiPostgresql
|
10
|
+
|
11
|
+
# pg
|
12
|
+
#
|
13
|
+
# List databases for an app
|
14
|
+
#
|
15
|
+
def index
|
16
|
+
validate_arguments!
|
17
|
+
|
18
|
+
if hpg_databases_with_info.empty?
|
19
|
+
display("#{app} has no azuki-postgresql databases.")
|
20
|
+
else
|
21
|
+
hpg_databases_with_info.keys.sort.each do |name|
|
22
|
+
display_db name, hpg_databases_with_info[name]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# pg:info [DATABASE]
|
28
|
+
#
|
29
|
+
# -x, --extended # Show extended information
|
30
|
+
#
|
31
|
+
# Display database information
|
32
|
+
#
|
33
|
+
# If DATABASE is not specified, displays all databases
|
34
|
+
#
|
35
|
+
def info
|
36
|
+
db = shift_argument
|
37
|
+
validate_arguments!
|
38
|
+
|
39
|
+
if db
|
40
|
+
attachment = hpg_resolve(db)
|
41
|
+
display_db attachment.display_name, hpg_info(attachment, options[:extended])
|
42
|
+
else
|
43
|
+
index
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# pg:promote DATABASE
|
48
|
+
#
|
49
|
+
# Sets DATABASE as your DATABASE_URL
|
50
|
+
#
|
51
|
+
def promote
|
52
|
+
unless db = shift_argument
|
53
|
+
error("Usage: azuki pg:promote DATABASE\nMust specify DATABASE to promote.")
|
54
|
+
end
|
55
|
+
validate_arguments!
|
56
|
+
|
57
|
+
attachment = hpg_resolve(db)
|
58
|
+
|
59
|
+
action "Promoting #{attachment.display_name} to DATABASE_URL" do
|
60
|
+
hpg_promote(attachment.url)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# pg:psql [DATABASE]
|
65
|
+
#
|
66
|
+
# Open a psql shell to the database
|
67
|
+
#
|
68
|
+
# defaults to DATABASE_URL databases if no DATABASE is specified
|
69
|
+
#
|
70
|
+
def psql
|
71
|
+
attachment = hpg_resolve(shift_argument, "DATABASE_URL")
|
72
|
+
validate_arguments!
|
73
|
+
|
74
|
+
uri = URI.parse( attachment.url )
|
75
|
+
begin
|
76
|
+
ENV["PGPASSWORD"] = uri.password
|
77
|
+
ENV["PGSSLMODE"] = 'require'
|
78
|
+
exec "psql -U #{uri.user} -h #{uri.host} -p #{uri.port || 5432} #{uri.path[1..-1]}"
|
79
|
+
rescue Errno::ENOENT
|
80
|
+
output_with_bang "The local psql command could not be located"
|
81
|
+
output_with_bang "For help installing psql, see http://devcenter.azukiapp.com/articles/local-postgresql"
|
82
|
+
abort
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# pg:reset DATABASE
|
87
|
+
#
|
88
|
+
# Delete all data in DATABASE
|
89
|
+
#
|
90
|
+
def reset
|
91
|
+
unless db = shift_argument
|
92
|
+
error("Usage: azuki pg:reset DATABASE\nMust specify DATABASE to reset.")
|
93
|
+
end
|
94
|
+
validate_arguments!
|
95
|
+
|
96
|
+
attachment = hpg_resolve(db) unless db == "SHARED_DATABASE"
|
97
|
+
return unless confirm_command
|
98
|
+
|
99
|
+
if db == "SHARED_DATABASE"
|
100
|
+
action("Resetting SHARED_DATABASE") { azuki.database_reset(app) }
|
101
|
+
else
|
102
|
+
action("Resetting #{attachment.display_name}") do
|
103
|
+
hpg_client(attachment).reset
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# pg:unfollow REPLICA
|
109
|
+
#
|
110
|
+
# stop a replica from following and make it a read/write database
|
111
|
+
#
|
112
|
+
def unfollow
|
113
|
+
unless db = shift_argument
|
114
|
+
error("Usage: azuki pg:unfollow REPLICA\nMust specify REPLICA to unfollow.")
|
115
|
+
end
|
116
|
+
validate_arguments!
|
117
|
+
|
118
|
+
replica = hpg_resolve(db)
|
119
|
+
replica_info = hpg_info(replica)
|
120
|
+
|
121
|
+
unless replica_info[:following]
|
122
|
+
error("#{replica.display_name} is not following another database.")
|
123
|
+
end
|
124
|
+
origin_url = replica_info[:following]
|
125
|
+
origin_name = database_name_from_url(origin_url)
|
126
|
+
|
127
|
+
output_with_bang "#{replica.display_name} will become writable and no longer"
|
128
|
+
output_with_bang "follow #{origin_name}. This cannot be undone."
|
129
|
+
return unless confirm_command
|
130
|
+
|
131
|
+
action "Unfollowing #{replica.display_name}" do
|
132
|
+
hpg_client(replica).unfollow
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# pg:wait [DATABASE]
|
137
|
+
#
|
138
|
+
# monitor database creation, exit when complete
|
139
|
+
#
|
140
|
+
# defaults to all databases if no DATABASE is specified
|
141
|
+
#
|
142
|
+
def wait
|
143
|
+
db = shift_argument
|
144
|
+
validate_arguments!
|
145
|
+
|
146
|
+
if db
|
147
|
+
wait_for hpg_resolve(db)
|
148
|
+
else
|
149
|
+
hpg_databases.values.each do |attach|
|
150
|
+
wait_for(attach)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# pg:credentials DATABASE
|
156
|
+
#
|
157
|
+
# Display the DATABASE credentials.
|
158
|
+
#
|
159
|
+
# --reset # Reset credentials on the specified database.
|
160
|
+
#
|
161
|
+
def credentials
|
162
|
+
unless db = shift_argument
|
163
|
+
error("Usage: azuki pg:credentials DATABASE\nMust specify DATABASE to display credentials.")
|
164
|
+
end
|
165
|
+
validate_arguments!
|
166
|
+
|
167
|
+
attachment = hpg_resolve(db)
|
168
|
+
|
169
|
+
if options[:reset]
|
170
|
+
action "Resetting credentials for #{attachment.display_name}" do
|
171
|
+
hpg_client(attachment).rotate_credentials
|
172
|
+
end
|
173
|
+
if attachment.primary_attachment?
|
174
|
+
forget_config!
|
175
|
+
attachment = hpg_resolve(db)
|
176
|
+
action "Promoting #{attachment.display_name}" do
|
177
|
+
hpg_promote(attachment.url)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
else
|
181
|
+
uri = URI.parse( attachment.url )
|
182
|
+
display "Connection info string:"
|
183
|
+
display " \"dbname=#{uri.path[1..-1]} host=#{uri.host} port=#{uri.port || 5432} user=#{uri.user} password=#{uri.password} sslmode=require\""
|
184
|
+
display "Connection URL:"
|
185
|
+
display " " + attachment.url
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def database_name_from_url(url)
|
193
|
+
vars = app_config_vars.reject {|key,value| key == 'DATABASE_URL'}
|
194
|
+
if var = vars.invert[url]
|
195
|
+
var.gsub(/_URL$/, '')
|
196
|
+
else
|
197
|
+
uri = URI.parse(url)
|
198
|
+
"Database on #{uri.host}:#{uri.port || 5432}#{uri.path}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def display_db(name, db)
|
203
|
+
styled_header(name)
|
204
|
+
styled_hash(db[:info].inject({}) do |hash, item|
|
205
|
+
hash.update(item["name"] => hpg_info_display(item))
|
206
|
+
end, db[:info].map {|item| item['name']})
|
207
|
+
|
208
|
+
display
|
209
|
+
end
|
210
|
+
|
211
|
+
def hpg_client(attachment)
|
212
|
+
Azuki::Client::AzukiPostgresql.new(attachment)
|
213
|
+
end
|
214
|
+
|
215
|
+
def hpg_databases_with_info
|
216
|
+
return @hpg_databases_with_info if @hpg_databases_with_info
|
217
|
+
|
218
|
+
@hpg_databases_with_info = Hash[ hpg_databases.map { |config, att| [att.display_name, hpg_info(att, options[:extended])] } ]
|
219
|
+
|
220
|
+
return @hpg_databases_with_info
|
221
|
+
end
|
222
|
+
|
223
|
+
def hpg_info(attachment, extended=false)
|
224
|
+
if attachment.resource_name == "SHARED_DATABASE"
|
225
|
+
data = api.get_app(app).body
|
226
|
+
{:info => [{
|
227
|
+
'name' => 'Data Size',
|
228
|
+
'values' => [format_bytes(data['database_size'])]
|
229
|
+
}]}
|
230
|
+
else
|
231
|
+
hpg_client(attachment).get_database(extended)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def hpg_info_display(item)
|
236
|
+
item["values"] = [item["value"]] if item["value"]
|
237
|
+
item["values"].map do |value|
|
238
|
+
if item["resolve_db_name"]
|
239
|
+
database_name_from_url(value)
|
240
|
+
else
|
241
|
+
value
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def ticking
|
247
|
+
ticks = 0
|
248
|
+
loop do
|
249
|
+
yield(ticks)
|
250
|
+
ticks +=1
|
251
|
+
sleep 1
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def wait_for(attach)
|
256
|
+
ticking do |ticks|
|
257
|
+
status = hpg_client(attach).get_wait_status
|
258
|
+
error status[:message] if status[:error?]
|
259
|
+
break if !status[:waiting?] && ticks.zero?
|
260
|
+
redisplay("Waiting for database %s... %s%s" % [
|
261
|
+
attach.display_name,
|
262
|
+
status[:waiting?] ? "#{spinner(ticks)} " : "",
|
263
|
+
status[:message]],
|
264
|
+
!status[:waiting?]) # only display a newline on the last tick
|
265
|
+
break unless status[:waiting?]
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|