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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +71 -0
  3. data/bin/azuki +17 -0
  4. data/data/cacert.pem +3988 -0
  5. data/lib/azuki.rb +17 -0
  6. data/lib/azuki/auth.rb +339 -0
  7. data/lib/azuki/cli.rb +38 -0
  8. data/lib/azuki/client.rb +764 -0
  9. data/lib/azuki/client/azuki_postgresql.rb +141 -0
  10. data/lib/azuki/client/cisaurus.rb +26 -0
  11. data/lib/azuki/client/pgbackups.rb +113 -0
  12. data/lib/azuki/client/rendezvous.rb +108 -0
  13. data/lib/azuki/client/ssl_endpoint.rb +25 -0
  14. data/lib/azuki/command.rb +294 -0
  15. data/lib/azuki/command/account.rb +23 -0
  16. data/lib/azuki/command/accounts.rb +34 -0
  17. data/lib/azuki/command/addons.rb +305 -0
  18. data/lib/azuki/command/apps.rb +393 -0
  19. data/lib/azuki/command/auth.rb +86 -0
  20. data/lib/azuki/command/base.rb +230 -0
  21. data/lib/azuki/command/certs.rb +209 -0
  22. data/lib/azuki/command/config.rb +137 -0
  23. data/lib/azuki/command/db.rb +218 -0
  24. data/lib/azuki/command/domains.rb +85 -0
  25. data/lib/azuki/command/drains.rb +46 -0
  26. data/lib/azuki/command/fork.rb +164 -0
  27. data/lib/azuki/command/git.rb +64 -0
  28. data/lib/azuki/command/help.rb +179 -0
  29. data/lib/azuki/command/keys.rb +115 -0
  30. data/lib/azuki/command/labs.rb +147 -0
  31. data/lib/azuki/command/logs.rb +45 -0
  32. data/lib/azuki/command/maintenance.rb +61 -0
  33. data/lib/azuki/command/pg.rb +269 -0
  34. data/lib/azuki/command/pgbackups.rb +329 -0
  35. data/lib/azuki/command/plugins.rb +110 -0
  36. data/lib/azuki/command/ps.rb +232 -0
  37. data/lib/azuki/command/regions.rb +22 -0
  38. data/lib/azuki/command/releases.rb +124 -0
  39. data/lib/azuki/command/run.rb +180 -0
  40. data/lib/azuki/command/sharing.rb +89 -0
  41. data/lib/azuki/command/ssl.rb +43 -0
  42. data/lib/azuki/command/stack.rb +62 -0
  43. data/lib/azuki/command/status.rb +51 -0
  44. data/lib/azuki/command/update.rb +47 -0
  45. data/lib/azuki/command/version.rb +23 -0
  46. data/lib/azuki/deprecated.rb +5 -0
  47. data/lib/azuki/deprecated/help.rb +38 -0
  48. data/lib/azuki/distribution.rb +9 -0
  49. data/lib/azuki/excon.rb +9 -0
  50. data/lib/azuki/helpers.rb +517 -0
  51. data/lib/azuki/helpers/azuki_postgresql.rb +165 -0
  52. data/lib/azuki/helpers/log_displayer.rb +70 -0
  53. data/lib/azuki/plugin.rb +163 -0
  54. data/lib/azuki/updater.rb +171 -0
  55. data/lib/azuki/version.rb +3 -0
  56. data/lib/vendor/azuki/okjson.rb +598 -0
  57. data/spec/azuki/auth_spec.rb +256 -0
  58. data/spec/azuki/client/azuki_postgresql_spec.rb +71 -0
  59. data/spec/azuki/client/pgbackups_spec.rb +43 -0
  60. data/spec/azuki/client/rendezvous_spec.rb +62 -0
  61. data/spec/azuki/client/ssl_endpoint_spec.rb +48 -0
  62. data/spec/azuki/client_spec.rb +564 -0
  63. data/spec/azuki/command/addons_spec.rb +601 -0
  64. data/spec/azuki/command/apps_spec.rb +351 -0
  65. data/spec/azuki/command/auth_spec.rb +38 -0
  66. data/spec/azuki/command/base_spec.rb +109 -0
  67. data/spec/azuki/command/certs_spec.rb +178 -0
  68. data/spec/azuki/command/config_spec.rb +144 -0
  69. data/spec/azuki/command/db_spec.rb +110 -0
  70. data/spec/azuki/command/domains_spec.rb +87 -0
  71. data/spec/azuki/command/drains_spec.rb +34 -0
  72. data/spec/azuki/command/fork_spec.rb +56 -0
  73. data/spec/azuki/command/git_spec.rb +144 -0
  74. data/spec/azuki/command/help_spec.rb +93 -0
  75. data/spec/azuki/command/keys_spec.rb +120 -0
  76. data/spec/azuki/command/labs_spec.rb +100 -0
  77. data/spec/azuki/command/logs_spec.rb +60 -0
  78. data/spec/azuki/command/maintenance_spec.rb +51 -0
  79. data/spec/azuki/command/pg_spec.rb +236 -0
  80. data/spec/azuki/command/pgbackups_spec.rb +307 -0
  81. data/spec/azuki/command/plugins_spec.rb +104 -0
  82. data/spec/azuki/command/ps_spec.rb +195 -0
  83. data/spec/azuki/command/releases_spec.rb +130 -0
  84. data/spec/azuki/command/run_spec.rb +83 -0
  85. data/spec/azuki/command/sharing_spec.rb +59 -0
  86. data/spec/azuki/command/stack_spec.rb +46 -0
  87. data/spec/azuki/command/status_spec.rb +48 -0
  88. data/spec/azuki/command/version_spec.rb +16 -0
  89. data/spec/azuki/command_spec.rb +211 -0
  90. data/spec/azuki/helpers/azuki_postgresql_spec.rb +155 -0
  91. data/spec/azuki/helpers_spec.rb +48 -0
  92. data/spec/azuki/plugin_spec.rb +172 -0
  93. data/spec/azuki/updater_spec.rb +44 -0
  94. data/spec/helper/legacy_help.rb +16 -0
  95. data/spec/spec.opts +1 -0
  96. data/spec/spec_helper.rb +224 -0
  97. data/spec/support/display_message_matcher.rb +49 -0
  98. data/spec/support/openssl_mock_helper.rb +8 -0
  99. metadata +211 -0
@@ -0,0 +1,155 @@
1
+ require "spec_helper"
2
+ require "azuki/helpers/azuki_postgresql"
3
+
4
+ include Azuki::Helpers::AzukiPostgresql
5
+
6
+ describe Azuki::Helpers::AzukiPostgresql do
7
+
8
+ before do
9
+ subject.forget_config!
10
+ subject.stub(:app_config_vars) { app_config_vars }
11
+ subject.stub(:app_attachments) { app_attachments }
12
+ end
13
+
14
+ let(:app_config_vars) do
15
+ {
16
+ "DATABASE_URL" => "postgres://default",
17
+ "AZUKI_POSTGRESQL_BLACK_URL" => "postgres://black",
18
+ "AZUKI_POSTGRESQL_IVORY_URL" => "postgres://default",
19
+ "SHARED_DATABASE_URL" => "postgres://shared"
20
+ }
21
+ end
22
+
23
+ let(:app_attachments) {
24
+ [ Attachment.new({ 'config_var' => 'AZUKI_POSTGRESQL_IVORY_URL',
25
+ 'resource' => {'name' => 'softly-mocking-123',
26
+ 'value' => 'postgres://default',
27
+ 'type' => 'azuki-postgresql:baku' }}),
28
+ Attachment.new({ 'config_var' => 'AZUKI_POSTGRESQL_BLACK_URL',
29
+ 'resource' => {'name' => 'quickly-yelling-2421',
30
+ 'value' => 'postgres://black',
31
+ 'type' => 'azuki-postgresql:zilla' }})
32
+ ]
33
+ }
34
+
35
+ context "when the DATABASE_URL has query options" do
36
+ let(:app_config_vars) do
37
+ {
38
+ "DATABASE_URL" => "postgres://default?pool=15",
39
+ "AZUKI_POSTGRESQL_BLACK_URL" => "postgres://black",
40
+ "AZUKI_POSTGRESQL_IVORY_URL" => "postgres://default",
41
+ "SHARED_DATABASE_URL" => "postgres://shared"
42
+ }
43
+ end
44
+
45
+ it "resolves DATABASE" do
46
+ att = subject.hpg_resolve('DATABASE')
47
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
48
+ att.url.should == "postgres://default"
49
+ end
50
+ end
51
+
52
+ context "when the DATABASE_URL has no query options" do
53
+ let(:app_config_vars) do
54
+ {
55
+ "DATABASE_URL" => "postgres://default",
56
+ "AZUKI_POSTGRESQL_BLACK_URL" => "postgres://black",
57
+ "AZUKI_POSTGRESQL_IVORY_URL" => "postgres://default",
58
+ "SHARED_DATABASE_URL" => "postgres://shared"
59
+ }
60
+ end
61
+
62
+ it "resolves DATABASE" do
63
+ att = subject.hpg_resolve('DATABASE')
64
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
65
+ att.url.should == "postgres://default"
66
+ end
67
+ end
68
+
69
+ it "resolves SHARED_DATABASE" do
70
+ att = subject.hpg_resolve('SHARED_DATABASE')
71
+ att.display_name.should == "SHARED_DATABASE"
72
+ att.url.should == "postgres://shared"
73
+ end
74
+
75
+ it "resolves default using NAME" do
76
+ att = subject.hpg_resolve('IVORY')
77
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
78
+ att.url.should == "postgres://default"
79
+ end
80
+
81
+ it "resolves non-default using NAME" do
82
+ att = subject.hpg_resolve('BLACK')
83
+ att.display_name.should == "AZUKI_POSTGRESQL_BLACK_URL"
84
+ att.url.should == "postgres://black"
85
+ end
86
+
87
+ it "resolves default using NAME_URL" do
88
+ att = subject.hpg_resolve('IVORY_URL')
89
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
90
+ att.url.should == "postgres://default"
91
+ end
92
+
93
+ it "resolves non-default using NAME_URL" do
94
+ att = subject.hpg_resolve('BLACK_URL')
95
+ att.display_name.should == "AZUKI_POSTGRESQL_BLACK_URL"
96
+ att.url.should == "postgres://black"
97
+ end
98
+
99
+ it "resolves default using lowercase" do
100
+ att = subject.hpg_resolve('ivory')
101
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
102
+ att.url.should == "postgres://default"
103
+ end
104
+
105
+ it "resolves non-default using lowercase" do
106
+ att = subject.hpg_resolve('black')
107
+ att.display_name.should == "AZUKI_POSTGRESQL_BLACK_URL"
108
+ att.url.should == "postgres://black"
109
+ end
110
+
111
+ it "resolves non-default using part of name" do
112
+ att = subject.hpg_resolve('bla')
113
+ att.display_name.should == "AZUKI_POSTGRESQL_BLACK_URL"
114
+ att.url.should == "postgres://black"
115
+ end
116
+
117
+ it "throws an error if it doesnt exist" do
118
+ subject.should_receive(:error).with("Unknown database: violet. Valid options are: DATABASE_URL, AZUKI_POSTGRESQL_BLACK_URL, AZUKI_POSTGRESQL_IVORY_URL, SHARED_DATABASE")
119
+ subject.hpg_resolve("violet")
120
+ end
121
+
122
+ context "default" do
123
+
124
+ it "errors if there is no default" do
125
+ subject.should_receive(:error).with("Unknown database. Valid options are: DATABASE_URL, AZUKI_POSTGRESQL_BLACK_URL, AZUKI_POSTGRESQL_IVORY_URL, SHARED_DATABASE")
126
+ subject.hpg_resolve(nil)
127
+ end
128
+
129
+ it "uses the default if nothing(nil) specified" do
130
+ att = subject.hpg_resolve(nil, "DATABASE_URL")
131
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
132
+ att.url.should == "postgres://default"
133
+ end
134
+
135
+ it "uses the default if nothing(empty) specified" do
136
+ att = subject.hpg_resolve('', "DATABASE_URL")
137
+ att.display_name.should == "AZUKI_POSTGRESQL_IVORY_URL (DATABASE_URL)"
138
+ att.url.should == "postgres://default"
139
+ end
140
+
141
+ it 'throws an error if given an empty string and asked for the default and there is no default' do
142
+ app_config_vars.delete 'DATABASE_URL'
143
+ subject.should_receive(:error).with("Unknown database. Valid options are: AZUKI_POSTGRESQL_BLACK_URL, AZUKI_POSTGRESQL_IVORY_URL, SHARED_DATABASE")
144
+ att = subject.hpg_resolve('', "DATABASE_URL")
145
+ end
146
+
147
+ it 'throws an error if given an empty string and asked for the default and the default doesnt match' do
148
+ app_config_vars['DATABASE_URL'] = 'something different'
149
+ subject.should_receive(:error).with("Unknown database. Valid options are: AZUKI_POSTGRESQL_BLACK_URL, AZUKI_POSTGRESQL_IVORY_URL, SHARED_DATABASE")
150
+ att = subject.hpg_resolve('', "DATABASE_URL")
151
+ end
152
+
153
+
154
+ end
155
+ end
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+ require "azuki/helpers"
3
+
4
+ module Azuki
5
+ describe Helpers do
6
+ include Azuki::Helpers
7
+
8
+ context "display_object" do
9
+
10
+ it "should display Array correctly" do
11
+ capture_stdout do
12
+ display_object([1,2,3])
13
+ end.should == <<-OUT
14
+ 1
15
+ 2
16
+ 3
17
+ OUT
18
+ end
19
+
20
+ it "should display { :header => [] } list correctly" do
21
+ capture_stdout do
22
+ display_object({:first_header => [1,2,3], :last_header => [7,8,9]})
23
+ end.should == <<-OUT
24
+ === first_header
25
+ 1
26
+ 2
27
+ 3
28
+
29
+ === last_header
30
+ 7
31
+ 8
32
+ 9
33
+
34
+ OUT
35
+ end
36
+
37
+ it "should display String properly" do
38
+ capture_stdout do
39
+ display_object('string')
40
+ end.should == <<-OUT
41
+ string
42
+ OUT
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,172 @@
1
+ require "spec_helper"
2
+ require "azuki/plugin"
3
+
4
+ module Azuki
5
+ describe Plugin do
6
+ include SandboxHelper
7
+
8
+ it "lives in ~/.azuki/plugins" do
9
+ Plugin.stub!(:home_directory).and_return('/home/user')
10
+ Plugin.directory.should == '/home/user/.azuki/plugins'
11
+ end
12
+
13
+ it "extracts the name from git urls" do
14
+ Plugin.new('git://github.com/azuki/plugin.git').name.should == 'plugin'
15
+ end
16
+
17
+ describe "management" do
18
+ before(:each) do
19
+ @sandbox = "/tmp/azuki_plugins_spec_#{Process.pid}"
20
+ FileUtils.mkdir_p(@sandbox)
21
+ Dir.stub!(:pwd).and_return(@sandbox)
22
+ Plugin.stub!(:directory).and_return(@sandbox)
23
+ end
24
+
25
+ after(:each) do
26
+ FileUtils.rm_rf(@sandbox)
27
+ end
28
+
29
+ it "lists installed plugins" do
30
+ FileUtils.mkdir_p(@sandbox + '/plugin1')
31
+ FileUtils.mkdir_p(@sandbox + '/plugin2')
32
+ Plugin.list.should include 'plugin1'
33
+ Plugin.list.should include 'plugin2'
34
+ end
35
+
36
+ it "installs pulling from the plugin url" do
37
+ plugin_folder = "/tmp/azuki_plugin"
38
+ FileUtils.mkdir_p(plugin_folder)
39
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
40
+ Plugin.new(plugin_folder).install
41
+ File.directory?("#{@sandbox}/azuki_plugin").should be_true
42
+ File.read("#{@sandbox}/azuki_plugin/README").should == "test\n"
43
+ end
44
+
45
+ it "reinstalls over old copies" do
46
+ plugin_folder = "/tmp/azuki_plugin"
47
+ FileUtils.mkdir_p(plugin_folder)
48
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
49
+ Plugin.new(plugin_folder).install
50
+ Plugin.new(plugin_folder).install
51
+ File.directory?("#{@sandbox}/azuki_plugin").should be_true
52
+ File.read("#{@sandbox}/azuki_plugin/README").should == "test\n"
53
+ end
54
+
55
+ context "update" do
56
+
57
+ before(:each) do
58
+ plugin_folder = "/tmp/azuki_plugin"
59
+ FileUtils.mkdir_p(plugin_folder)
60
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
61
+ Plugin.new(plugin_folder).install
62
+ `cd #{plugin_folder} && echo 'updated' > README && git add . && git commit -m 'my plugin update'`
63
+ end
64
+
65
+ it "updates existing copies" do
66
+ Plugin.new('azuki_plugin').update
67
+ File.directory?("#{@sandbox}/azuki_plugin").should be_true
68
+ File.read("#{@sandbox}/azuki_plugin/README").should == "updated\n"
69
+ end
70
+
71
+ it "warns on legacy plugins" do
72
+ `cd #{@sandbox}/azuki_plugin && git config --unset branch.master.remote`
73
+ stderr = capture_stderr do
74
+ begin
75
+ Plugin.new('azuki_plugin').update
76
+ rescue SystemExit
77
+ end
78
+ end
79
+ stderr.should == <<-STDERR
80
+ ! azuki_plugin is a legacy plugin installation.
81
+ ! Enable updating by reinstalling with `azuki plugins:install`.
82
+ STDERR
83
+ end
84
+
85
+ it "raises exception on symlinked plugins" do
86
+ `cd #{@sandbox} && ln -s azuki_plugin azuki_plugin_symlink`
87
+ lambda { Plugin.new('azuki_plugin_symlink').update }.should raise_error Azuki::Plugin::ErrorUpdatingSymlinkPlugin
88
+ end
89
+
90
+ end
91
+
92
+
93
+ it "uninstalls removing the folder" do
94
+ FileUtils.mkdir_p(@sandbox + '/plugin1')
95
+ Plugin.new('git://github.com/azuki/plugin1.git').uninstall
96
+ Plugin.list.should == []
97
+ end
98
+
99
+ it "adds the lib folder in the plugin to the load path, if present" do
100
+ FileUtils.mkdir_p(@sandbox + '/plugin/lib')
101
+ File.open(@sandbox + '/plugin/lib/my_custom_plugin_file.rb', 'w') { |f| f.write "" }
102
+ Plugin.load!
103
+ lambda { require 'my_custom_plugin_file' }.should_not raise_error(LoadError)
104
+ end
105
+
106
+ it "loads init.rb, if present" do
107
+ FileUtils.mkdir_p(@sandbox + '/plugin')
108
+ File.open(@sandbox + '/plugin/init.rb', 'w') { |f| f.write "LoadedInit = true" }
109
+ Plugin.load!
110
+ LoadedInit.should be_true
111
+ end
112
+
113
+ describe "when there are plugin load errors" do
114
+ before(:each) do
115
+ FileUtils.mkdir_p(@sandbox + '/some_plugin/lib')
116
+ File.open(@sandbox + '/some_plugin/init.rb', 'w') { |f| f.write "require 'some_non_existant_file'" }
117
+ end
118
+
119
+ it "should not throw an error" do
120
+ capture_stderr do
121
+ lambda { Plugin.load! }.should_not raise_error
122
+ end
123
+ end
124
+
125
+ it "should fail gracefully" do
126
+ stderr = capture_stderr do
127
+ Plugin.load!
128
+ end
129
+ stderr.should include('some_non_existant_file (LoadError)')
130
+ end
131
+
132
+ it "should still load other plugins" do
133
+ FileUtils.mkdir_p(@sandbox + '/some_plugin_2/lib')
134
+ File.open(@sandbox + '/some_plugin_2/init.rb', 'w') { |f| f.write "LoadedPlugin2 = true" }
135
+ stderr = capture_stderr do
136
+ Plugin.load!
137
+ end
138
+ stderr.should include('some_non_existant_file (LoadError)')
139
+ LoadedPlugin2.should be_true
140
+ end
141
+ end
142
+
143
+ describe "deprecated plugins" do
144
+ before(:each) do
145
+ FileUtils.mkdir_p(@sandbox + '/azuki-releases/lib')
146
+ end
147
+
148
+ after(:each) do
149
+ FileUtils.rm_rf(@sandbox + '/azuki-releases/lib')
150
+ end
151
+
152
+ it "should show confirmation to remove deprecated plugins if in an interactive shell" do
153
+ old_stdin_isatty = STDIN.isatty
154
+ STDIN.stub!(:isatty).and_return(true)
155
+ Plugin.should_receive(:confirm).with("The plugin azuki-releases has been deprecated. Would you like to remove it? (y/N)").and_return(true)
156
+ Plugin.should_receive(:remove_plugin).with("azuki-releases")
157
+ Plugin.load!
158
+ STDIN.stub!(:isatty).and_return(old_stdin_isatty)
159
+ end
160
+
161
+ it "should not prompt for deprecation if not in an interactive shell" do
162
+ old_stdin_isatty = STDIN.isatty
163
+ STDIN.stub!(:isatty).and_return(false)
164
+ Plugin.should_not_receive(:confirm)
165
+ Plugin.should_not_receive(:remove_plugin).with("azuki-releases")
166
+ Plugin.load!
167
+ STDIN.stub!(:isatty).and_return(old_stdin_isatty)
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+ require "azuki/updater"
3
+ require "azuki/version"
4
+
5
+ module Azuki
6
+ describe Updater do
7
+
8
+ it "calculates the latest local version" do
9
+ Azuki::Updater.latest_local_version.should == Azuki::VERSION
10
+ end
11
+
12
+ it "calculates compare_versions" do
13
+ Azuki::Updater.compare_versions('1.1.1', '1.1.1').should == 0
14
+
15
+ Azuki::Updater.compare_versions('2.1.1', '1.1.1').should == 1
16
+ Azuki::Updater.compare_versions('1.1.1', '2.1.1').should == -1
17
+
18
+ Azuki::Updater.compare_versions('1.2.1', '1.1.1').should == 1
19
+ Azuki::Updater.compare_versions('1.1.1', '1.2.1').should == -1
20
+
21
+ Azuki::Updater.compare_versions('1.1.2', '1.1.1').should == 1
22
+ Azuki::Updater.compare_versions('1.1.1', '1.1.2').should == -1
23
+
24
+ Azuki::Updater.compare_versions('2.1.1', '1.2.1').should == 1
25
+ Azuki::Updater.compare_versions('1.2.1', '2.1.1').should == -1
26
+
27
+ Azuki::Updater.compare_versions('2.1.1', '1.1.2').should == 1
28
+ Azuki::Updater.compare_versions('1.1.2', '2.1.1').should == -1
29
+
30
+ Azuki::Updater.compare_versions('1.2.4', '1.2.3').should == 1
31
+ Azuki::Updater.compare_versions('1.2.3', '1.2.4').should == -1
32
+
33
+ Azuki::Updater.compare_versions('1.2.1', '1.2' ).should == 1
34
+ Azuki::Updater.compare_versions('1.2', '1.2.1').should == -1
35
+
36
+ Azuki::Updater.compare_versions('1.1.1.pre1', '1.1.1').should == 1
37
+ Azuki::Updater.compare_versions('1.1.1', '1.1.1.pre1').should == -1
38
+
39
+ Azuki::Updater.compare_versions('1.1.1.pre2', '1.1.1.pre1').should == 1
40
+ Azuki::Updater.compare_versions('1.1.1.pre1', '1.1.1.pre2').should == -1
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ require "azuki/command/help"
2
+
3
+ Azuki::Command::Help.group("Foo Group") do |foo|
4
+ foo.command "foo:bar", "do a bar to foo"
5
+ foo.space
6
+ foo.command "foo:baz", "do a baz to foo"
7
+ end
8
+
9
+ class Azuki::Command::Foo < Azuki::Command::Base
10
+ def bar
11
+ end
12
+
13
+ def baz
14
+ end
15
+ end
16
+
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,224 @@
1
+ $stdin = File.new("/dev/null")
2
+
3
+ require "rubygems"
4
+
5
+ require "excon"
6
+ Excon.defaults[:mock] = true
7
+
8
+ # ensure these are around for errors
9
+ # as their require is generally deferred
10
+ require "azuki-api"
11
+ require "rest_client"
12
+
13
+ require "azuki/cli"
14
+ require "rspec"
15
+ require "rr"
16
+ require "fakefs/safe"
17
+ require 'tmpdir'
18
+ require "webmock/rspec"
19
+
20
+ include WebMock::API
21
+
22
+ WebMock::HttpLibAdapters::ExconAdapter.disable!
23
+
24
+ def api
25
+ Azuki::API.new(:api_key => "pass", :mock => true)
26
+ end
27
+
28
+ def stub_api_request(method, path)
29
+ stub_request(method, "https://api.azukiapp.com#{path}")
30
+ end
31
+
32
+ def prepare_command(klass)
33
+ command = klass.new
34
+ command.stub!(:app).and_return("example")
35
+ command.stub!(:ask).and_return("")
36
+ command.stub!(:display)
37
+ command.stub!(:hputs)
38
+ command.stub!(:hprint)
39
+ command.stub!(:azuki).and_return(mock('azuki client', :host => 'azukiapp.com'))
40
+ command
41
+ end
42
+
43
+ def execute(command_line)
44
+ extend RR::Adapters::RRMethods
45
+
46
+ args = command_line.split(" ")
47
+ command = args.shift
48
+
49
+ Azuki::Command.load
50
+ object, method = Azuki::Command.prepare_run(command, args)
51
+
52
+ any_instance_of(Azuki::Command::Base) do |base|
53
+ stub(base).app.returns("example")
54
+ end
55
+
56
+ stub(Azuki::Auth).get_credentials.returns(['email@example.com', 'apikey01'])
57
+ stub(Azuki::Auth).api_key.returns('apikey01')
58
+
59
+ original_stdin, original_stderr, original_stdout = $stdin, $stderr, $stdout
60
+
61
+ $stdin = captured_stdin = StringIO.new
62
+ $stderr = captured_stderr = StringIO.new
63
+ $stdout = captured_stdout = StringIO.new
64
+ class << captured_stdout
65
+ def tty?
66
+ true
67
+ end
68
+ end
69
+
70
+ begin
71
+ object.send(method)
72
+ rescue SystemExit
73
+ ensure
74
+ $stdin, $stderr, $stdout = original_stdin, original_stderr, original_stdout
75
+ Azuki::Command.current_command = nil
76
+ end
77
+
78
+ [captured_stderr.string, captured_stdout.string]
79
+ end
80
+
81
+ def any_instance_of(klass, &block)
82
+ extend RR::Adapters::RRMethods
83
+ any_instance_of(klass, &block)
84
+ end
85
+
86
+ def run(command_line)
87
+ capture_stdout do
88
+ begin
89
+ Azuki::CLI.start(*command_line.split(" "))
90
+ rescue SystemExit
91
+ end
92
+ end
93
+ end
94
+
95
+ alias azuki run
96
+
97
+ def capture_stderr(&block)
98
+ original_stderr = $stderr
99
+ $stderr = captured_stderr = StringIO.new
100
+ begin
101
+ yield
102
+ ensure
103
+ $stderr = original_stderr
104
+ end
105
+ captured_stderr.string
106
+ end
107
+
108
+ def capture_stdout(&block)
109
+ original_stdout = $stdout
110
+ $stdout = captured_stdout = StringIO.new
111
+ begin
112
+ yield
113
+ ensure
114
+ $stdout = original_stdout
115
+ end
116
+ captured_stdout.string
117
+ end
118
+
119
+ def fail_command(message)
120
+ raise_error(Azuki::Command::CommandFailed, message)
121
+ end
122
+
123
+ def stub_core
124
+ @stubbed_core ||= begin
125
+ stubbed_core = nil
126
+ any_instance_of(Azuki::Client) do |core|
127
+ stubbed_core = stub(core)
128
+ end
129
+ stub(Azuki::Auth).user.returns("email@example.com")
130
+ stub(Azuki::Auth).password.returns("pass")
131
+ stub(Azuki::Client).auth.returns("apikey01")
132
+ stubbed_core
133
+ end
134
+ end
135
+
136
+ def stub_pg
137
+ @stubbed_pg ||= begin
138
+ stubbed_pg = nil
139
+ any_instance_of(Azuki::Client::AzukiPostgresql) do |pg|
140
+ stubbed_pg = stub(pg)
141
+ end
142
+ stubbed_pg
143
+ end
144
+ end
145
+
146
+ def stub_pgbackups
147
+ @stubbed_pgbackups ||= begin
148
+ stubbed_pgbackups = nil
149
+ any_instance_of(Azuki::Client::Pgbackups) do |pgbackups|
150
+ stubbed_pgbackups = stub(pgbackups)
151
+ end
152
+ stubbed_pgbackups
153
+ end
154
+ end
155
+
156
+ def stub_rendezvous
157
+ @stubbed_rendezvous ||= begin
158
+ stubbed_rendezvous = nil
159
+ any_instance_of(Azuki::Client::Rendezvous) do |rendezvous|
160
+ stubbed_rendezvous = stub(rendezvous)
161
+ end
162
+ stubbed_rendezvous
163
+ end
164
+ end
165
+
166
+ def stub_cisaurus
167
+ @stub_cisaurus ||= begin
168
+ stub_cisaurus = nil
169
+ any_instance_of(Azuki::Client::Cisaurus) do |cisaurus|
170
+ stub_cisaurus = stub(cisaurus)
171
+ end
172
+ stub_cisaurus
173
+ end
174
+ end
175
+
176
+ def with_blank_git_repository(&block)
177
+ sandbox = File.join(Dir.tmpdir, "azuki", Process.pid.to_s)
178
+ FileUtils.mkdir_p(sandbox)
179
+
180
+ old_dir = Dir.pwd
181
+ Dir.chdir(sandbox)
182
+
183
+ `git init`
184
+ block.call
185
+
186
+ FileUtils.rm_rf(sandbox)
187
+ ensure
188
+ Dir.chdir(old_dir)
189
+ end
190
+
191
+ def taps_available?
192
+ begin
193
+ require "taps/operation"
194
+ true
195
+ rescue LoadError
196
+ false
197
+ end
198
+ end
199
+
200
+ module SandboxHelper
201
+ def bash(cmd)
202
+ `#{cmd}`
203
+ end
204
+ end
205
+
206
+ require "azuki/helpers"
207
+ module Azuki::Helpers
208
+ @home_directory = Dir.mktmpdir
209
+ undef_method :home_directory
210
+ def home_directory
211
+ @home_directory
212
+ end
213
+ end
214
+
215
+ require "support/display_message_matcher"
216
+
217
+ RSpec.configure do |config|
218
+ config.color_enabled = true
219
+ config.include DisplayMessageMatcher
220
+ config.order = 'rand'
221
+ config.before { Azuki::Helpers.error_with_failure = false }
222
+ config.after { RR.reset }
223
+ end
224
+