azuki 0.0.1
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/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,178 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "azuki/command/certs"
|
|
3
|
+
|
|
4
|
+
module Azuki::Command
|
|
5
|
+
describe Certs do
|
|
6
|
+
let(:certificate_details) {
|
|
7
|
+
<<-CERTIFICATE_DETAILS.chomp
|
|
8
|
+
Common Name(s): example.org
|
|
9
|
+
Expires At: 2013-08-01 21:34 UTC
|
|
10
|
+
Issuer: /C=US/ST=California/L=San Francisco/O=Azuki by Salesforce/CN=secure.example.org
|
|
11
|
+
Starts At: 2012-08-01 21:34 UTC
|
|
12
|
+
Subject: /C=US/ST=California/L=San Francisco/O=Azuki by Salesforce/CN=secure.example.org
|
|
13
|
+
SSL certificate is self signed.
|
|
14
|
+
CERTIFICATE_DETAILS
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let(:endpoint) {
|
|
18
|
+
{ 'cname' => 'tokyo-1050.azukissl.com',
|
|
19
|
+
'ssl_cert' => {
|
|
20
|
+
'ca_signed?' => false,
|
|
21
|
+
'cert_domains' => [ 'example.org' ],
|
|
22
|
+
'starts_at' => "2012-08-01 21:34:23 UTC",
|
|
23
|
+
'expires_at' => "2013-08-01 21:34:23 UTC",
|
|
24
|
+
'issuer' => '/C=US/ST=California/L=San Francisco/O=Azuki by Salesforce/CN=secure.example.org',
|
|
25
|
+
'subject' => '/C=US/ST=California/L=San Francisco/O=Azuki by Salesforce/CN=secure.example.org',
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
let(:endpoint2) {
|
|
30
|
+
{ 'cname' => 'akita-7777.azukissl.com',
|
|
31
|
+
'ssl_cert' => {
|
|
32
|
+
'ca_signed?' => true,
|
|
33
|
+
'cert_domains' => [ 'azukiapp.com' ],
|
|
34
|
+
'starts_at' => "2012-08-01 21:34:23 UTC",
|
|
35
|
+
'expires_at' => "2013-08-01 21:34:23 UTC",
|
|
36
|
+
'issuer' => '/C=US/ST=California/L=San Francisco/O=Azuki by Salesforce/CN=secure.example.org',
|
|
37
|
+
'subject' => '/C=US/ST=California/L=San Francisco/O=Azuki by Salesforce/CN=secure.example.org',
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe "certs" do
|
|
43
|
+
it "shows a list of certs" do
|
|
44
|
+
stub_core.ssl_endpoint_list("example").returns([endpoint, endpoint2])
|
|
45
|
+
stderr, stdout = execute("certs")
|
|
46
|
+
stdout.should == <<-STDOUT
|
|
47
|
+
Endpoint Common Name(s) Expires Trusted
|
|
48
|
+
------------------------ -------------- -------------------- -------
|
|
49
|
+
tokyo-1050.azukissl.com example.org 2013-08-01 21:34 UTC False
|
|
50
|
+
akita-7777.azukissl.com azukiapp.com 2013-08-01 21:34 UTC True
|
|
51
|
+
STDOUT
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "warns about no SSL Endpoints if the app has no certs" do
|
|
55
|
+
stub_core.ssl_endpoint_list("example").returns([])
|
|
56
|
+
stderr, stdout = execute("certs")
|
|
57
|
+
stdout.should == <<-STDOUT
|
|
58
|
+
example has no SSL Endpoints.
|
|
59
|
+
Use `azuki certs:add CRT KEY` to add one.
|
|
60
|
+
STDOUT
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "certs:add" do
|
|
65
|
+
it "adds an endpoint" do
|
|
66
|
+
File.should_receive(:read).with("pem_file").and_return("pem content")
|
|
67
|
+
File.should_receive(:read).with("key_file").and_return("key content")
|
|
68
|
+
stub_core.ssl_endpoint_add('example', 'pem content', 'key content').returns(endpoint)
|
|
69
|
+
|
|
70
|
+
stderr, stdout = execute("certs:add --bypass pem_file key_file")
|
|
71
|
+
stdout.should == <<-STDOUT
|
|
72
|
+
Adding SSL Endpoint to example... done
|
|
73
|
+
example now served by tokyo-1050.azukissl.com
|
|
74
|
+
Certificate details:
|
|
75
|
+
#{certificate_details}
|
|
76
|
+
STDOUT
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "shows usage if two arguments are not provided" do
|
|
80
|
+
lambda { execute("certs:add --bypass") }.should raise_error(CommandFailed, /Usage:/)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "certs:info" do
|
|
85
|
+
it "shows certificate details" do
|
|
86
|
+
stub_core.ssl_endpoint_list("example").returns([endpoint])
|
|
87
|
+
stub_core.ssl_endpoint_info('example', 'tokyo-1050.azukissl.com').returns(endpoint)
|
|
88
|
+
|
|
89
|
+
stderr, stdout = execute("certs:info")
|
|
90
|
+
stdout.should == <<-STDOUT
|
|
91
|
+
Fetching SSL Endpoint tokyo-1050.azukissl.com info for example... done
|
|
92
|
+
Certificate details:
|
|
93
|
+
#{certificate_details}
|
|
94
|
+
STDOUT
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "shows an error if an app has no endpoints" do
|
|
98
|
+
stub_core.ssl_endpoint_list("example").returns([])
|
|
99
|
+
|
|
100
|
+
stderr, stdout = execute("certs:info")
|
|
101
|
+
stderr.should == <<-STDERR
|
|
102
|
+
! example has no SSL Endpoints.
|
|
103
|
+
STDERR
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "certs:remove" do
|
|
108
|
+
it "removes an endpoint" do
|
|
109
|
+
stub_core.ssl_endpoint_list("example").returns([endpoint])
|
|
110
|
+
stub_core.ssl_endpoint_remove('example', 'tokyo-1050.azukissl.com').returns(endpoint)
|
|
111
|
+
|
|
112
|
+
stderr, stdout = execute("certs:remove")
|
|
113
|
+
stdout.should include "Removing SSL Endpoint tokyo-1050.azukissl.com from example..."
|
|
114
|
+
stdout.should include "NOTE: Billing is still active. Remove SSL Endpoint add-on to stop billing."
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "shows an error if an app has no endpoints" do
|
|
118
|
+
stub_core.ssl_endpoint_list("example").returns([])
|
|
119
|
+
|
|
120
|
+
stderr, stdout = execute("certs:remove")
|
|
121
|
+
stderr.should == <<-STDERR
|
|
122
|
+
! example has no SSL Endpoints.
|
|
123
|
+
STDERR
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe "certs:update" do
|
|
128
|
+
before do
|
|
129
|
+
File.should_receive(:read).with("pem_file").and_return("pem content")
|
|
130
|
+
File.should_receive(:read).with("key_file").and_return("key content")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "updates an endpoint" do
|
|
134
|
+
stub_core.ssl_endpoint_list("example").returns([endpoint])
|
|
135
|
+
stub_core.ssl_endpoint_update('example', 'tokyo-1050.azukissl.com', 'pem content', 'key content').returns(endpoint)
|
|
136
|
+
|
|
137
|
+
stderr, stdout = execute("certs:update --bypass pem_file key_file")
|
|
138
|
+
stdout.should == <<-STDOUT
|
|
139
|
+
Updating SSL Endpoint tokyo-1050.azukissl.com for example... done
|
|
140
|
+
Updated certificate details:
|
|
141
|
+
#{certificate_details}
|
|
142
|
+
STDOUT
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "shows an error if an app has no endpoints" do
|
|
146
|
+
stub_core.ssl_endpoint_list("example").returns([])
|
|
147
|
+
|
|
148
|
+
stderr, stdout = execute("certs:update --bypass pem_file key_file")
|
|
149
|
+
stderr.should == <<-STDERR
|
|
150
|
+
! example has no SSL Endpoints.
|
|
151
|
+
STDERR
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
describe "certs:rollback" do
|
|
156
|
+
it "performs a rollback on an endpoint" do
|
|
157
|
+
stub_core.ssl_endpoint_list("example").returns([endpoint])
|
|
158
|
+
stub_core.ssl_endpoint_rollback('example', 'tokyo-1050.azukissl.com').returns(endpoint)
|
|
159
|
+
|
|
160
|
+
stderr, stdout = execute("certs:rollback")
|
|
161
|
+
stdout.should == <<-STDOUT
|
|
162
|
+
Rolling back SSL Endpoint tokyo-1050.azukissl.com for example... done
|
|
163
|
+
New active certificate details:
|
|
164
|
+
#{certificate_details}
|
|
165
|
+
STDOUT
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "shows an error if an app has no endpoints" do
|
|
169
|
+
stub_core.ssl_endpoint_list("example").returns([])
|
|
170
|
+
|
|
171
|
+
stderr, stdout = execute("certs:rollback")
|
|
172
|
+
stderr.should == <<-STDERR
|
|
173
|
+
! example has no SSL Endpoints.
|
|
174
|
+
STDERR
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "azuki/command/config"
|
|
3
|
+
|
|
4
|
+
module Azuki::Command
|
|
5
|
+
describe Config do
|
|
6
|
+
before(:each) do
|
|
7
|
+
stub_core
|
|
8
|
+
api.post_app("name" => "example", "stack" => "cedar")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after(:each) do
|
|
12
|
+
api.delete_app("example")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "shows all configs" do
|
|
16
|
+
api.put_config_vars("example", { 'FOO_BAR' => 'one', 'BAZ_QUX' => 'two' })
|
|
17
|
+
stderr, stdout = execute("config")
|
|
18
|
+
stderr.should == ""
|
|
19
|
+
stdout.should == <<-STDOUT
|
|
20
|
+
=== example Config Vars
|
|
21
|
+
BAZ_QUX: two
|
|
22
|
+
FOO_BAR: one
|
|
23
|
+
STDOUT
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "does not trim long values" do
|
|
27
|
+
api.put_config_vars("example", { 'LONG' => 'A' * 60 })
|
|
28
|
+
stderr, stdout = execute("config")
|
|
29
|
+
stderr.should == ""
|
|
30
|
+
stdout.should == <<-STDOUT
|
|
31
|
+
=== example Config Vars
|
|
32
|
+
LONG: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
33
|
+
STDOUT
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "handles when value is nil" do
|
|
37
|
+
api.put_config_vars("example", { 'FOO_BAR' => 'one', 'BAZ_QUX' => nil })
|
|
38
|
+
stderr, stdout = execute("config")
|
|
39
|
+
stderr.should == ""
|
|
40
|
+
stdout.should == <<-STDOUT
|
|
41
|
+
=== example Config Vars
|
|
42
|
+
BAZ_QUX:
|
|
43
|
+
FOO_BAR: one
|
|
44
|
+
STDOUT
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "handles when value is a boolean" do
|
|
48
|
+
api.put_config_vars("example", { 'FOO_BAR' => 'one', 'BAZ_QUX' => true })
|
|
49
|
+
stderr, stdout = execute("config")
|
|
50
|
+
stderr.should == ""
|
|
51
|
+
stdout.should == <<-STDOUT
|
|
52
|
+
=== example Config Vars
|
|
53
|
+
BAZ_QUX: true
|
|
54
|
+
FOO_BAR: one
|
|
55
|
+
STDOUT
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "shows configs in a shell compatible format" do
|
|
59
|
+
api.put_config_vars("example", { 'A' => 'one', 'B' => 'two three' })
|
|
60
|
+
stderr, stdout = execute("config --shell")
|
|
61
|
+
stderr.should == ""
|
|
62
|
+
stdout.should == <<-STDOUT
|
|
63
|
+
A=one
|
|
64
|
+
B=two three
|
|
65
|
+
STDOUT
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "shows a single config for get" do
|
|
69
|
+
api.put_config_vars("example", { 'LONG' => 'A' * 60 })
|
|
70
|
+
stderr, stdout = execute("config:get LONG")
|
|
71
|
+
stderr.should == ""
|
|
72
|
+
stdout.should == <<-STDOUT
|
|
73
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
74
|
+
STDOUT
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context("set") do
|
|
78
|
+
|
|
79
|
+
it "sets config vars" do
|
|
80
|
+
stderr, stdout = execute("config:set A=1 B=2")
|
|
81
|
+
stderr.should == ""
|
|
82
|
+
stdout.should == <<-STDOUT
|
|
83
|
+
Setting config vars and restarting example... done, v1
|
|
84
|
+
A: 1
|
|
85
|
+
B: 2
|
|
86
|
+
STDOUT
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "allows config vars with = in the value" do
|
|
90
|
+
stderr, stdout = execute("config:set A=b=c")
|
|
91
|
+
stderr.should == ""
|
|
92
|
+
stdout.should == <<-STDOUT
|
|
93
|
+
Setting config vars and restarting example... done, v1
|
|
94
|
+
A: b=c
|
|
95
|
+
STDOUT
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "sets config vars without changing case" do
|
|
99
|
+
stderr, stdout = execute("config:set a=b")
|
|
100
|
+
stderr.should == ""
|
|
101
|
+
stdout.should == <<-STDOUT
|
|
102
|
+
Setting config vars and restarting example... done, v1
|
|
103
|
+
a: b
|
|
104
|
+
STDOUT
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe "config:unset" do
|
|
110
|
+
|
|
111
|
+
it "exits with a help notice when no keys are provides" do
|
|
112
|
+
stderr, stdout = execute("config:unset")
|
|
113
|
+
stderr.should == <<-STDERR
|
|
114
|
+
! Usage: azuki config:unset KEY1 [KEY2 ...]
|
|
115
|
+
! Must specify KEY to unset.
|
|
116
|
+
STDERR
|
|
117
|
+
stdout.should == ""
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context "when one key is provided" do
|
|
121
|
+
|
|
122
|
+
it "unsets a single key" do
|
|
123
|
+
stderr, stdout = execute("config:unset A")
|
|
124
|
+
stderr.should == ""
|
|
125
|
+
stdout.should == <<-STDOUT
|
|
126
|
+
Unsetting A and restarting example... done, v1
|
|
127
|
+
STDOUT
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context "when more than one key is provided" do
|
|
132
|
+
|
|
133
|
+
it "unsets all given keys" do
|
|
134
|
+
stderr, stdout = execute("config:unset A B")
|
|
135
|
+
stderr.should == ""
|
|
136
|
+
stdout.should == <<-STDOUT
|
|
137
|
+
Unsetting A and restarting example... done, v1
|
|
138
|
+
Unsetting B and restarting example... done, v2
|
|
139
|
+
STDOUT
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "azuki/command/db"
|
|
3
|
+
|
|
4
|
+
module Azuki::Command
|
|
5
|
+
describe Db do
|
|
6
|
+
before do
|
|
7
|
+
@db = prepare_command(Db)
|
|
8
|
+
@taps_client = mock('taps client')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "pull database" do
|
|
12
|
+
pending("requires taps") unless taps_available?
|
|
13
|
+
@db.stub!(:args).and_return(['postgres://postgres@localhost/db'])
|
|
14
|
+
opts = { :database_url => 'postgres://postgres@localhost/db', :default_chunksize => 1000, :indexes_first => true }
|
|
15
|
+
@db.should_receive(:taps_client).with(:pull, opts)
|
|
16
|
+
@db.should_receive(:confirm_command).and_return(true)
|
|
17
|
+
@db.pull
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "push database" do
|
|
21
|
+
pending("requires taps") unless taps_available?
|
|
22
|
+
@db.stub!(:args).and_return(['postgres://postgres@localhost/db'])
|
|
23
|
+
opts = { :database_url => 'postgres://postgres@localhost/db', :default_chunksize => 1000, :indexes_first => true }
|
|
24
|
+
@db.should_receive(:taps_client).with(:push, opts)
|
|
25
|
+
@db.should_receive(:confirm_command).and_return(true)
|
|
26
|
+
@db.push
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "without PostgreSQL" do
|
|
30
|
+
it "defaults host to 127.0.0.1 with a username" do
|
|
31
|
+
@db.send(:uri_hash_to_url, {'scheme' => 'db', 'username' => 'user', 'path' => 'database'}).should == 'db://user@127.0.0.1/database'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "with PostgreSQL" do
|
|
36
|
+
it "handles lack of host as UNIX domain socket connection" do
|
|
37
|
+
@db.send(:uri_hash_to_url, {'scheme' => 'postgres', 'path' => 'database'}).should == 'postgres:/database'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "handles the lack of a username properly" do
|
|
42
|
+
@db.send(:uri_hash_to_url, {'scheme' => 'db', 'path' => 'database'}).should == 'db://127.0.0.1/database'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "handles integer port number" do
|
|
46
|
+
@db.send(:uri_hash_to_url, {'scheme' => 'db', 'path' => 'database', 'port' => 9000}).should == 'db://127.0.0.1:9000/database'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "maps --tables to the taps table_filter option" do
|
|
50
|
+
@db.stub!(:args).and_return(["sqlite://local.db"])
|
|
51
|
+
@db.stub!(:options).and_return(:tables => "tags,countries")
|
|
52
|
+
opts = @db.send(:parse_taps_opts)
|
|
53
|
+
opts[:table_filter].should == "(^tags$|^countries$)"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "handles both a url and a --confirm on the command line" do
|
|
57
|
+
pending("requires taps") unless taps_available?
|
|
58
|
+
Azuki::Command.stub!(:current_options).and_return(:confirm => "example")
|
|
59
|
+
@db.stub!(:args).and_return(["mysql://user:pass@host/db"])
|
|
60
|
+
opts = { :database_url => 'mysql://user:pass@host/db', :default_chunksize => 1000, :indexes_first => true }
|
|
61
|
+
@db.should_receive(:taps_client).with(:pull, opts)
|
|
62
|
+
@db.pull
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "handles no url and --confirm on the command line" do
|
|
66
|
+
pending("requires taps") unless taps_available?
|
|
67
|
+
Azuki::Command.stub!(:current_options).and_return(:confirm => "example")
|
|
68
|
+
opts = { :database_url => 'mysql://user:pass@host/db', :default_chunksize => 1000, :indexes_first => true }
|
|
69
|
+
@db.should_receive(:parse_database_yml).and_return("mysql://user:pass@host/db")
|
|
70
|
+
@db.should_receive(:taps_client).with(:pull, opts)
|
|
71
|
+
@db.pull
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "works with a file-based url" do
|
|
75
|
+
pending("requires taps") unless taps_available?
|
|
76
|
+
url = "sqlite://tmp/foo.db"
|
|
77
|
+
Azuki::Command.stub(:current_options).and_return(:confirm => "example")
|
|
78
|
+
@db.stub(:args).and_return([url])
|
|
79
|
+
@db.should_receive(:taps_client).with(:pull, hash_including(:database_url => url))
|
|
80
|
+
@db.pull
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "with erb in the database.yml" do
|
|
84
|
+
before do
|
|
85
|
+
@rails_env = ENV["RAILS_ENV"]
|
|
86
|
+
ENV["RAILS_ENV"] = "development"
|
|
87
|
+
|
|
88
|
+
FakeFS.activate!
|
|
89
|
+
FileUtils.mkdir_p "config"
|
|
90
|
+
File.open("config/database.yml", "w") do |file|
|
|
91
|
+
file.puts <<-YAML
|
|
92
|
+
development:
|
|
93
|
+
adapter: db
|
|
94
|
+
host: localhost
|
|
95
|
+
database: <%= 'db'+'1' %>
|
|
96
|
+
YAML
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
after do
|
|
101
|
+
FakeFS.deactivate!
|
|
102
|
+
ENV["RAILS_ENV"] = @rails_env
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "handles ERB code in YAML" do
|
|
106
|
+
@db.send(:parse_database_yml).should == 'db://localhost/db1?encoding=utf8'
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "azuki/command/domains"
|
|
3
|
+
|
|
4
|
+
module Azuki::Command
|
|
5
|
+
describe Domains do
|
|
6
|
+
|
|
7
|
+
before(:all) do
|
|
8
|
+
api.post_app("name" => "example", "stack" => "cedar")
|
|
9
|
+
api.post_addon("example", "custom_domains:basic")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
after(:all) do
|
|
13
|
+
api.delete_app("example")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
before(:each) do
|
|
17
|
+
stub_core
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context("index") do
|
|
21
|
+
|
|
22
|
+
it "lists message with no domains" do
|
|
23
|
+
stderr, stdout = execute("domains")
|
|
24
|
+
stderr.should == ""
|
|
25
|
+
stdout.should == <<-STDOUT
|
|
26
|
+
example has no domain names.
|
|
27
|
+
STDOUT
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "lists domains when some exist" do
|
|
31
|
+
api.post_domain("example", "example.com")
|
|
32
|
+
stderr, stdout = execute("domains")
|
|
33
|
+
stderr.should == ""
|
|
34
|
+
stdout.should == <<-STDOUT
|
|
35
|
+
=== example Domain Names
|
|
36
|
+
example.com
|
|
37
|
+
|
|
38
|
+
STDOUT
|
|
39
|
+
api.delete_domain("example", "example.com")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "adds domain names" do
|
|
45
|
+
stderr, stdout = execute("domains:add example.com")
|
|
46
|
+
stderr.should == ""
|
|
47
|
+
stdout.should == <<-STDOUT
|
|
48
|
+
Adding example.com to example... done
|
|
49
|
+
STDOUT
|
|
50
|
+
api.delete_domain("example", "example.com")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "shows usage if no domain specified for add" do
|
|
54
|
+
stderr, stdout = execute("domains:add")
|
|
55
|
+
stderr.should == <<-STDERR
|
|
56
|
+
! Usage: azuki domains:add DOMAIN
|
|
57
|
+
! Must specify DOMAIN to add.
|
|
58
|
+
STDERR
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "removes domain names" do
|
|
62
|
+
api.post_domain("example", "example.com")
|
|
63
|
+
stderr, stdout = execute("domains:remove example.com")
|
|
64
|
+
stderr.should == ""
|
|
65
|
+
stdout.should == <<-STDOUT
|
|
66
|
+
Removing example.com from example... done
|
|
67
|
+
STDOUT
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "shows usage if no domain specified for remove" do
|
|
71
|
+
stderr, stdout = execute("domains:remove")
|
|
72
|
+
stderr.should == <<-STDERR
|
|
73
|
+
! Usage: azuki domains:remove DOMAIN
|
|
74
|
+
! Must specify DOMAIN to remove.
|
|
75
|
+
STDERR
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "removes all domain names" do
|
|
79
|
+
stub_core.remove_domains("example")
|
|
80
|
+
stderr, stdout = execute("domains:clear")
|
|
81
|
+
stderr.should == ""
|
|
82
|
+
stdout.should == <<-STDOUT
|
|
83
|
+
Removing all domain names from example... done
|
|
84
|
+
STDOUT
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|