af 0.3.22 → 0.5.0.beta.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 +14 -6
- data/LICENSE +1277 -24
- data/Rakefile +24 -87
- data/bin/af +7 -2
- data/lib/af/version.rb +3 -0
- data/lib/vmc.rb +7 -2
- data/lib/vmc/cli.rb +475 -0
- data/lib/vmc/cli/app/app.rb +45 -0
- data/lib/vmc/cli/app/apps.rb +105 -0
- data/lib/vmc/cli/app/base.rb +82 -0
- data/lib/vmc/cli/app/crashes.rb +46 -0
- data/lib/vmc/cli/app/delete.rb +95 -0
- data/lib/vmc/cli/app/deprecated.rb +11 -0
- data/lib/vmc/cli/app/env.rb +78 -0
- data/lib/vmc/cli/app/files.rb +137 -0
- data/lib/vmc/cli/app/health.rb +26 -0
- data/lib/vmc/cli/app/instances.rb +53 -0
- data/lib/vmc/cli/app/logs.rb +76 -0
- data/lib/vmc/cli/app/push.rb +107 -0
- data/lib/vmc/cli/app/push/create.rb +150 -0
- data/lib/vmc/cli/app/push/interactions.rb +100 -0
- data/lib/vmc/cli/app/push/sync.rb +64 -0
- data/lib/vmc/cli/app/rename.rb +39 -0
- data/lib/vmc/cli/app/restart.rb +20 -0
- data/lib/vmc/cli/app/scale.rb +71 -0
- data/lib/vmc/cli/app/start.rb +93 -0
- data/lib/vmc/cli/app/stats.rb +67 -0
- data/lib/vmc/cli/app/stop.rb +27 -0
- data/lib/vmc/cli/domain/base.rb +12 -0
- data/lib/vmc/cli/domain/domains.rb +40 -0
- data/lib/vmc/cli/domain/map.rb +55 -0
- data/lib/vmc/cli/domain/unmap.rb +56 -0
- data/lib/vmc/cli/help.rb +16 -0
- data/lib/vmc/cli/interactive.rb +105 -0
- data/lib/vmc/cli/organization/base.rb +14 -0
- data/lib/vmc/cli/organization/create.rb +32 -0
- data/lib/vmc/cli/organization/delete.rb +73 -0
- data/lib/vmc/cli/organization/org.rb +45 -0
- data/lib/vmc/cli/organization/orgs.rb +35 -0
- data/lib/vmc/cli/organization/rename.rb +36 -0
- data/lib/vmc/cli/route/base.rb +12 -0
- data/lib/vmc/cli/route/map.rb +80 -0
- data/lib/vmc/cli/route/routes.rb +26 -0
- data/lib/vmc/cli/route/unmap.rb +94 -0
- data/lib/vmc/cli/service/base.rb +8 -0
- data/lib/vmc/cli/service/bind.rb +44 -0
- data/lib/vmc/cli/service/create.rb +126 -0
- data/lib/vmc/cli/service/delete.rb +86 -0
- data/lib/vmc/cli/service/rename.rb +35 -0
- data/lib/vmc/cli/service/service.rb +42 -0
- data/lib/vmc/cli/service/services.rb +115 -0
- data/lib/vmc/cli/service/unbind.rb +38 -0
- data/lib/vmc/cli/space/base.rb +21 -0
- data/lib/vmc/cli/space/create.rb +56 -0
- data/lib/vmc/cli/space/delete.rb +95 -0
- data/lib/vmc/cli/space/rename.rb +39 -0
- data/lib/vmc/cli/space/space.rb +64 -0
- data/lib/vmc/cli/space/spaces.rb +55 -0
- data/lib/vmc/cli/space/take.rb +16 -0
- data/lib/vmc/cli/start/base.rb +80 -0
- data/lib/vmc/cli/start/colors.rb +13 -0
- data/lib/vmc/cli/start/info.rb +122 -0
- data/lib/vmc/cli/start/login.rb +92 -0
- data/lib/vmc/cli/start/logout.rb +13 -0
- data/lib/vmc/cli/start/target.rb +64 -0
- data/lib/vmc/cli/start/target_interactions.rb +37 -0
- data/lib/vmc/cli/start/targets.rb +16 -0
- data/lib/vmc/cli/user/base.rb +29 -0
- data/lib/vmc/cli/user/create.rb +39 -0
- data/lib/vmc/cli/user/delete.rb +25 -0
- data/lib/vmc/cli/user/passwd.rb +50 -0
- data/lib/vmc/cli/user/register.rb +42 -0
- data/lib/vmc/cli/user/users.rb +32 -0
- data/lib/vmc/constants.rb +13 -0
- data/lib/vmc/detect.rb +134 -0
- data/lib/vmc/errors.rb +17 -0
- data/lib/vmc/plugin.rb +56 -0
- data/lib/vmc/spacing.rb +89 -0
- data/lib/vmc/spec_helper.rb +1 -0
- data/lib/vmc/test_support.rb +4 -0
- data/lib/vmc/test_support/command_helper.rb +32 -0
- data/lib/vmc/test_support/common_input_examples.rb +14 -0
- data/lib/vmc/test_support/fake_home_dir.rb +16 -0
- data/lib/vmc/test_support/interact_helper.rb +29 -0
- data/lib/vmc/version.rb +3 -0
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/main.rb +6 -0
- data/spec/features/new_user_flow_spec.rb +71 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/vmc/cli/app/base_spec.rb +17 -0
- data/spec/vmc/cli/app/delete_spec.rb +188 -0
- data/spec/vmc/cli/app/instances_spec.rb +65 -0
- data/spec/vmc/cli/app/push/create_spec.rb +571 -0
- data/spec/vmc/cli/app/push_spec.rb +369 -0
- data/spec/vmc/cli/app/rename_spec.rb +104 -0
- data/spec/vmc/cli/app/scale_spec.rb +81 -0
- data/spec/vmc/cli/app/stats_spec.rb +62 -0
- data/spec/vmc/cli/domain/map_spec.rb +140 -0
- data/spec/vmc/cli/domain/unmap_spec.rb +73 -0
- data/spec/vmc/cli/organization/orgs_spec.rb +108 -0
- data/spec/vmc/cli/organization/rename_spec.rb +113 -0
- data/spec/vmc/cli/route/map_spec.rb +138 -0
- data/spec/vmc/cli/route/unmap_spec.rb +215 -0
- data/spec/vmc/cli/service/bind_spec.rb +25 -0
- data/spec/vmc/cli/service/delete_spec.rb +22 -0
- data/spec/vmc/cli/service/rename_spec.rb +105 -0
- data/spec/vmc/cli/service/service_spec.rb +23 -0
- data/spec/vmc/cli/service/unbind_spec.rb +25 -0
- data/spec/vmc/cli/space/rename_spec.rb +102 -0
- data/spec/vmc/cli/space/spaces_spec.rb +104 -0
- data/spec/vmc/cli/start/info_spec.rb +153 -0
- data/spec/vmc/cli/start/login_spec.rb +71 -0
- data/spec/vmc/cli/user/create_spec.rb +54 -0
- data/spec/vmc/cli/user/passwd_spec.rb +102 -0
- data/spec/vmc/cli/user/register_spec.rb +148 -0
- data/spec/vmc/cli_spec.rb +448 -0
- data/spec/vmc/detect_spec.rb +54 -0
- metadata +231 -124
- data/README.md +0 -155
- data/caldecott_helper/Gemfile +0 -10
- data/caldecott_helper/Gemfile.lock +0 -48
- data/caldecott_helper/server.rb +0 -43
- data/config/clients.yml +0 -17
- data/config/micro/offline.conf +0 -2
- data/config/micro/paths.yml +0 -22
- data/config/micro/refresh_ip.rb +0 -20
- data/lib/cli.rb +0 -48
- data/lib/cli/commands/admin.rb +0 -81
- data/lib/cli/commands/apps.rb +0 -1358
- data/lib/cli/commands/base.rb +0 -233
- data/lib/cli/commands/manifest.rb +0 -56
- data/lib/cli/commands/micro.rb +0 -115
- data/lib/cli/commands/misc.rb +0 -147
- data/lib/cli/commands/services.rb +0 -217
- data/lib/cli/commands/user.rb +0 -70
- data/lib/cli/config.rb +0 -176
- data/lib/cli/console_helper.rb +0 -163
- data/lib/cli/core_ext.rb +0 -122
- data/lib/cli/errors.rb +0 -19
- data/lib/cli/file_helper.rb +0 -123
- data/lib/cli/frameworks.rb +0 -265
- data/lib/cli/manifest_helper.rb +0 -316
- data/lib/cli/runner.rb +0 -633
- data/lib/cli/services_helper.rb +0 -104
- data/lib/cli/tunnel_helper.rb +0 -336
- data/lib/cli/usage.rb +0 -129
- data/lib/cli/version.rb +0 -7
- data/lib/cli/zip_util.rb +0 -102
- data/lib/vmc/client.rb +0 -574
- data/lib/vmc/const.rb +0 -27
- data/lib/vmc/micro.rb +0 -56
- data/lib/vmc/micro/switcher/base.rb +0 -97
- data/lib/vmc/micro/switcher/darwin.rb +0 -19
- data/lib/vmc/micro/switcher/dummy.rb +0 -15
- data/lib/vmc/micro/switcher/linux.rb +0 -16
- data/lib/vmc/micro/switcher/windows.rb +0 -31
- data/lib/vmc/micro/vmrun.rb +0 -158
data/lib/vmc/errors.rb
ADDED
data/lib/vmc/plugin.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require "set"
|
|
2
|
+
require "yaml"
|
|
3
|
+
|
|
4
|
+
require "vmc/constants"
|
|
5
|
+
require "vmc/cli"
|
|
6
|
+
|
|
7
|
+
module VMC
|
|
8
|
+
module Plugin
|
|
9
|
+
@@plugins = []
|
|
10
|
+
|
|
11
|
+
def self.load_all
|
|
12
|
+
# auto-load gems with 'vmc-plugin' in their name
|
|
13
|
+
matching =
|
|
14
|
+
if Gem::Specification.respond_to? :find_all
|
|
15
|
+
Gem::Specification.find_all do |s|
|
|
16
|
+
s.name =~ /vmc-plugin/
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
Gem.source_index.find_name(/vmc-plugin/)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
enabled = Set.new(matching.collect(&:name))
|
|
23
|
+
|
|
24
|
+
vmc_gems = Gem.loaded_specs["vmc"]
|
|
25
|
+
((vmc_gems && vmc_gems.dependencies) || Gem.loaded_specs.values).each do |dep|
|
|
26
|
+
if dep.name =~ /vmc-plugin/
|
|
27
|
+
require "#{dep.name}/plugin"
|
|
28
|
+
enabled.delete dep.name
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# allow explicit enabling/disabling of gems via config
|
|
33
|
+
plugins = File.expand_path(VMC::PLUGINS_FILE)
|
|
34
|
+
if File.exists?(plugins) && yaml = YAML.load_file(plugins)
|
|
35
|
+
enabled += yaml["enabled"] if yaml["enabled"]
|
|
36
|
+
enabled -= yaml["disabled"] if yaml["disabled"]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# load up each gem's 'plugin' file
|
|
40
|
+
#
|
|
41
|
+
# we require this file specifically so people can require the gem
|
|
42
|
+
# without it plugging into VMC
|
|
43
|
+
enabled.each do |gemname|
|
|
44
|
+
begin
|
|
45
|
+
require "#{gemname}/plugin"
|
|
46
|
+
rescue Gem::LoadError => e
|
|
47
|
+
puts "Failed to load #{gemname}:"
|
|
48
|
+
puts " #{e}"
|
|
49
|
+
puts
|
|
50
|
+
puts "You may need to update or remove this plugin."
|
|
51
|
+
puts
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/vmc/spacing.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module VMC
|
|
2
|
+
module Spacing
|
|
3
|
+
@@indentation = 0
|
|
4
|
+
|
|
5
|
+
def indented
|
|
6
|
+
@@indentation += 1
|
|
7
|
+
yield
|
|
8
|
+
ensure
|
|
9
|
+
@@indentation -= 1
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def line(msg = "")
|
|
13
|
+
return puts "" if msg.empty?
|
|
14
|
+
|
|
15
|
+
start_line(msg)
|
|
16
|
+
puts ""
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def start_line(msg)
|
|
20
|
+
print " " * @@indentation unless quiet?
|
|
21
|
+
print msg
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def lines(blob)
|
|
25
|
+
blob.each_line do |line|
|
|
26
|
+
start_line(line)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
line
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def quiet?
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def spaced(vals)
|
|
37
|
+
num = 0
|
|
38
|
+
vals.each do |val|
|
|
39
|
+
line unless quiet? || num == 0
|
|
40
|
+
yield val
|
|
41
|
+
num += 1
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def tabular(*rows)
|
|
46
|
+
spacings = []
|
|
47
|
+
rows.each do |row|
|
|
48
|
+
next unless row
|
|
49
|
+
|
|
50
|
+
row.each.with_index do |col, i|
|
|
51
|
+
next unless col
|
|
52
|
+
|
|
53
|
+
width = text_width(col)
|
|
54
|
+
|
|
55
|
+
if !spacings[i] || width > spacings[i]
|
|
56
|
+
spacings[i] = width
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
columns = spacings.size
|
|
62
|
+
rows.each do |row|
|
|
63
|
+
next unless row
|
|
64
|
+
|
|
65
|
+
row.each.with_index do |col, i|
|
|
66
|
+
next unless col
|
|
67
|
+
|
|
68
|
+
start_line justify(col, spacings[i])
|
|
69
|
+
print " " unless i + 1 == columns
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
line
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def trim_escapes(str)
|
|
77
|
+
str.gsub(/\e\[\d+m/, "")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def text_width(str)
|
|
81
|
+
trim_escapes(str).size
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def justify(str, width)
|
|
85
|
+
trimmed = trim_escapes(str)
|
|
86
|
+
str.ljust(width + (str.size - trimmed.size))
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.expand_path("../../../spec/spec_helper", __FILE__)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module VMC::TestSupport::CommandHelper
|
|
2
|
+
def vmc(argv)
|
|
3
|
+
Mothership.new.exit_status 0
|
|
4
|
+
stub(VMC::CLI).exit { |code| code }
|
|
5
|
+
capture_output { VMC::CLI.start(argv + ["--debug"]) }
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def expect_status_and_output(status = 0, out = "", err = "")
|
|
9
|
+
expect([
|
|
10
|
+
status,
|
|
11
|
+
stdout.string.strip_progress_dots,
|
|
12
|
+
stderr.string.strip_progress_dots
|
|
13
|
+
]).to eq([status, out, err])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def bool_flag(flag)
|
|
17
|
+
"#{'no-' unless send(flag)}#{flag.to_s.gsub('_', '-')}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
attr_reader :stdout, :stderr, :status
|
|
21
|
+
|
|
22
|
+
def capture_output
|
|
23
|
+
real_stdout = $stdout
|
|
24
|
+
real_stderr = $stderr
|
|
25
|
+
$stdout = @stdout = StringIO.new
|
|
26
|
+
$stderr = @stderr = StringIO.new
|
|
27
|
+
@status = yield
|
|
28
|
+
ensure
|
|
29
|
+
$stdout = real_stdout
|
|
30
|
+
$stderr = real_stderr
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
shared_examples_for 'inputs must have descriptions' do
|
|
2
|
+
describe 'inputs' do
|
|
3
|
+
subject { command.inputs }
|
|
4
|
+
|
|
5
|
+
it "is not missing any descriptions" do
|
|
6
|
+
subject.each do |_, attrs|
|
|
7
|
+
next if attrs[:hidden]
|
|
8
|
+
|
|
9
|
+
expect(attrs[:description]).to be
|
|
10
|
+
expect(attrs[:description].strip).to_not be_empty
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module VMC::TestSupport::FakeHomeDir
|
|
2
|
+
def self.included(klass)
|
|
3
|
+
def klass.use_fake_home_dir(&block)
|
|
4
|
+
around do |example|
|
|
5
|
+
dir = instance_exec(&block)
|
|
6
|
+
original_home_dir = ENV['HOME']
|
|
7
|
+
ENV['HOME'] = dir
|
|
8
|
+
begin
|
|
9
|
+
example.call
|
|
10
|
+
ensure
|
|
11
|
+
ENV['HOME'] = original_home_dir
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module VMC::TestSupport::InteractHelper
|
|
2
|
+
def stub_ask(*args, &block)
|
|
3
|
+
a_stub = nil
|
|
4
|
+
any_instance_of VMC::CLI do |interactive|
|
|
5
|
+
a_stub = stub(interactive).ask(*args, &block)
|
|
6
|
+
end
|
|
7
|
+
a_stub
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def mock_ask(*args, &block)
|
|
11
|
+
a_mock = nil
|
|
12
|
+
any_instance_of VMC::CLI do |interactive|
|
|
13
|
+
a_mock = mock(interactive).ask(*args, &block)
|
|
14
|
+
end
|
|
15
|
+
a_mock
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def dont_allow_ask(*args)
|
|
19
|
+
any_instance_of VMC::CLI do |interactive|
|
|
20
|
+
dont_allow(interactive).ask(*args)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def mock_with_progress(message)
|
|
25
|
+
any_instance_of VMC::CLI do |interactive|
|
|
26
|
+
mock(interactive).with_progress(message) { |_, block| block.call }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/vmc/version.rb
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require "webmock/rspec"
|
|
3
|
+
|
|
4
|
+
if ENV['VMC_TEST_USER'] && ENV['VMC_TEST_PASSWORD'] && ENV['VMC_TEST_TARGET']
|
|
5
|
+
describe 'A new user tries to use VMC against v1 production' do
|
|
6
|
+
let(:target) { ENV['VMC_TEST_TARGET'] }
|
|
7
|
+
let(:username) { ENV['VMC_TEST_USER'] }
|
|
8
|
+
let(:password) { ENV['VMC_TEST_PASSWORD'] }
|
|
9
|
+
let(:output) { StringIO.new }
|
|
10
|
+
let(:out) { output.string.strip_progress_dots }
|
|
11
|
+
|
|
12
|
+
let(:app) do
|
|
13
|
+
fuzz = defined?(TRAVIS_BUILD_ID) ? TRAVIS_BUILD_ID : Time.new.to_f.to_s.gsub(".", "_")
|
|
14
|
+
"hello-sinatra-#{fuzz}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
FileUtils.rm_rf File.expand_path(VMC::CONFIG_DIR)
|
|
19
|
+
WebMock.allow_net_connect!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after { vmc %W(delete #{app} -f --no-script) }
|
|
23
|
+
|
|
24
|
+
it 'and pushes a simple sinatra app using defaults as much as possible' do
|
|
25
|
+
vmc %W[target #{target} --no-script]
|
|
26
|
+
expect_status_and_output 0, <<-OUT.strip_heredoc
|
|
27
|
+
Setting target to https://#{target}... OK
|
|
28
|
+
OUT
|
|
29
|
+
|
|
30
|
+
vmc %W[login #{username} --password #{password} --no-script]
|
|
31
|
+
expect_status_and_output 0, <<-OUT.strip_heredoc
|
|
32
|
+
target: https://#{target}
|
|
33
|
+
|
|
34
|
+
Authenticating... OK
|
|
35
|
+
OUT
|
|
36
|
+
|
|
37
|
+
vmc %W[app #{app} --no-script]
|
|
38
|
+
expect_status_and_output 1, "", <<-OUT.strip_heredoc
|
|
39
|
+
Unknown app '#{app}'.
|
|
40
|
+
OUT
|
|
41
|
+
|
|
42
|
+
Dir.chdir("#{SPEC_ROOT}/assets/hello-sinatra") do
|
|
43
|
+
vmc %W[push #{app} --runtime ruby19 --domain #{app}-vmc-test.cloudfoundry.com -f --no-script]
|
|
44
|
+
expect_status_and_output 0, <<-OUT.strip_heredoc
|
|
45
|
+
Creating #{app}... OK
|
|
46
|
+
|
|
47
|
+
Updating #{app}... OK
|
|
48
|
+
Uploading #{app}... OK
|
|
49
|
+
Starting #{app}... OK
|
|
50
|
+
Checking #{app}... OK
|
|
51
|
+
OUT
|
|
52
|
+
|
|
53
|
+
vmc %W[push #{app} --no-script]
|
|
54
|
+
expect_status_and_output 0, <<-OUT.strip_heredoc
|
|
55
|
+
Uploading #{app}... OK
|
|
56
|
+
Stopping #{app}... OK
|
|
57
|
+
|
|
58
|
+
Starting #{app}... OK
|
|
59
|
+
Checking #{app}... OK
|
|
60
|
+
OUT
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
vmc %W[delete #{app} -f --no-script]
|
|
64
|
+
expect_status_and_output 0, <<-OUT.strip_heredoc
|
|
65
|
+
Deleting #{app}... OK
|
|
66
|
+
OUT
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
$stderr.puts 'Skipping integration specs; please provide $VMC_TEST_TARGET, $VMC_TEST_USER, and $VMC_TEST_PASSWORD'
|
|
71
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
SPEC_ROOT = File.dirname(__FILE__).freeze
|
|
2
|
+
|
|
3
|
+
require "rspec"
|
|
4
|
+
require "cfoundry"
|
|
5
|
+
require "cfoundry/test_support"
|
|
6
|
+
require "vmc"
|
|
7
|
+
require "vmc/test_support"
|
|
8
|
+
require "webmock"
|
|
9
|
+
|
|
10
|
+
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
|
|
11
|
+
require file
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
RSpec.configure do |c|
|
|
15
|
+
c.include Fake::FakeMethods
|
|
16
|
+
c.include V1Fake::FakeMethods
|
|
17
|
+
c.mock_with :rr
|
|
18
|
+
|
|
19
|
+
c.include VMC::TestSupport::FakeHomeDir
|
|
20
|
+
c.include VMC::TestSupport::CommandHelper
|
|
21
|
+
c.include VMC::TestSupport::InteractHelper
|
|
22
|
+
|
|
23
|
+
c.before(:all) do
|
|
24
|
+
WebMock.disable_net_connect!
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
c.before do
|
|
28
|
+
VMC::CLI.send(:class_variable_set, :@@client, nil)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class String
|
|
33
|
+
def strip_heredoc
|
|
34
|
+
min = scan(/^[ \t]*(?=\S)/).min
|
|
35
|
+
indent = min ? min.size : 0
|
|
36
|
+
gsub(/^[ \t]{#{indent}}/, '')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def strip_progress_dots
|
|
40
|
+
gsub(/\. \x08([\x08\. ]+)/, "... ")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def name_list(xs)
|
|
45
|
+
if xs.empty?
|
|
46
|
+
"none"
|
|
47
|
+
else
|
|
48
|
+
xs.collect(&:name).join(", ")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def invoke_cli(cli, *args)
|
|
53
|
+
stub.proxy(cli).invoke.with_any_args
|
|
54
|
+
stub(cli.class).new { cli }
|
|
55
|
+
cli.invoke(*args)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def stub_output(cli)
|
|
59
|
+
stub(cli).print
|
|
60
|
+
stub(cli).puts
|
|
61
|
+
stub(Interact::Progress::Dots).start!
|
|
62
|
+
stub(Interact::Progress::Dots).stop!
|
|
63
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require "vmc/cli/app/base"
|
|
3
|
+
|
|
4
|
+
describe VMC::App::Base do
|
|
5
|
+
describe '#human_size' do
|
|
6
|
+
let(:base) { VMC::App::Base.new }
|
|
7
|
+
|
|
8
|
+
it { base.human_size(1_023).should == "1023.0B" }
|
|
9
|
+
it { base.human_size(1_024).should == "1.0K" }
|
|
10
|
+
it { base.human_size(1_024 * 1_024).should == "1.0M" }
|
|
11
|
+
it { base.human_size(1_024 * 1_024 * 1.5).should == "1.5M" }
|
|
12
|
+
it { base.human_size(1_024 * 1_024 * 1_024).should == "1.0G" }
|
|
13
|
+
it { base.human_size(1_024 * 1_024 * 1_024 * 1.5).should == "1.5G" }
|
|
14
|
+
it { base.human_size(1_024 * 1_024 * 1_024 * 1.234, 3).should == "1.234G" }
|
|
15
|
+
it { base.human_size(31395840).should == "29.9M" } # tests against floating point errors
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require "vmc/cli/app/delete"
|
|
3
|
+
|
|
4
|
+
describe VMC::App::Delete do
|
|
5
|
+
let(:global) { { :color => false, :quiet => true } }
|
|
6
|
+
let(:inputs) { {} }
|
|
7
|
+
let(:given) { {} }
|
|
8
|
+
let(:client) { fake_client }
|
|
9
|
+
let(:app) {}
|
|
10
|
+
let(:new_name) { "some-new-name" }
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
any_instance_of(VMC::CLI) do |cli|
|
|
14
|
+
stub(cli).client { client }
|
|
15
|
+
stub(cli).precondition { nil }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
subject { Mothership.new.invoke(:delete, inputs, given, global) }
|
|
20
|
+
|
|
21
|
+
describe 'metadata' do
|
|
22
|
+
let(:command) { Mothership.commands[:delete] }
|
|
23
|
+
|
|
24
|
+
describe 'command' do
|
|
25
|
+
subject { command }
|
|
26
|
+
its(:description) { should eq "Delete an application" }
|
|
27
|
+
it { expect(Mothership::Help.group(:apps, :manage)).to include(subject) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
include_examples 'inputs must have descriptions'
|
|
31
|
+
|
|
32
|
+
describe 'arguments' do
|
|
33
|
+
subject { command.arguments }
|
|
34
|
+
it 'has the correct argument order' do
|
|
35
|
+
should eq([{ :type => :splat, :value => nil, :name => :apps }])
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'when there are no apps' do
|
|
41
|
+
context 'and an app is given' do
|
|
42
|
+
let(:given) { { :app => "some-app" } }
|
|
43
|
+
it { expect { subject }.to raise_error(VMC::UserError, "Unknown app 'some-app'.") }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'and an app is not given' do
|
|
47
|
+
it { expect { subject }.to raise_error(VMC::UserError, "No applications.") }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when there are apps' do
|
|
52
|
+
let(:client) { fake_client(:apps => apps) }
|
|
53
|
+
let(:apps) { [basic_app, app_with_orphans, app_without_orphans] }
|
|
54
|
+
let(:service_1) { fake :service_instance }
|
|
55
|
+
let(:service_2) { fake :service_instance }
|
|
56
|
+
let(:basic_app) { fake(:app, :name => "basic_app") }
|
|
57
|
+
let(:app_with_orphans) {
|
|
58
|
+
fake :app,
|
|
59
|
+
:name => "app_with_orphans",
|
|
60
|
+
:service_bindings => [
|
|
61
|
+
fake(:service_binding, :service_instance => service_1),
|
|
62
|
+
fake(:service_binding, :service_instance => service_2)
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
let(:app_without_orphans) {
|
|
66
|
+
fake :app,
|
|
67
|
+
:name => "app_without_orphans",
|
|
68
|
+
:service_bindings => [
|
|
69
|
+
fake(:service_binding, :service_instance => service_1)
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
context 'and no app is given' do
|
|
74
|
+
it 'asks for the app' do
|
|
75
|
+
mock_ask("Delete which application?", anything) { basic_app }
|
|
76
|
+
stub_ask { true }
|
|
77
|
+
stub(basic_app).delete!
|
|
78
|
+
subject
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'and a basic app is given' do
|
|
83
|
+
let(:deleted_app) { basic_app }
|
|
84
|
+
let(:given) { { :app => deleted_app.name } }
|
|
85
|
+
|
|
86
|
+
context 'and it asks for confirmation' do
|
|
87
|
+
context 'and the user answers no' do
|
|
88
|
+
it 'does not delete the application' do
|
|
89
|
+
mock_ask("Really delete #{deleted_app.name}?", anything) { false }
|
|
90
|
+
dont_allow(deleted_app).delete!
|
|
91
|
+
subject
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'and the user answers yes' do
|
|
96
|
+
it 'deletes the application' do
|
|
97
|
+
mock_ask("Really delete #{deleted_app.name}?", anything) { true }
|
|
98
|
+
mock(deleted_app).delete!
|
|
99
|
+
subject
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context 'and --force is given' do
|
|
105
|
+
let(:global) { { :force => true, :color => false, :quiet => true } }
|
|
106
|
+
|
|
107
|
+
it 'deletes the application without asking to confirm' do
|
|
108
|
+
dont_allow_ask
|
|
109
|
+
mock(deleted_app).delete!
|
|
110
|
+
subject
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'and an app with orphaned services is given' do
|
|
116
|
+
let(:deleted_app) { app_with_orphans }
|
|
117
|
+
let(:inputs) { { :app => deleted_app } }
|
|
118
|
+
|
|
119
|
+
context 'and it asks for confirmation' do
|
|
120
|
+
context 'and the user answers yes' do
|
|
121
|
+
it 'asks to delete orphaned services' do
|
|
122
|
+
stub_ask("Really delete #{deleted_app.name}?", anything) { true }
|
|
123
|
+
stub(deleted_app).delete!
|
|
124
|
+
|
|
125
|
+
stub(service_2).invalidate!
|
|
126
|
+
|
|
127
|
+
mock_ask("Delete orphaned service #{service_2.name}?", anything) { true }
|
|
128
|
+
|
|
129
|
+
any_instance_of(VMC::App::Delete) do |del|
|
|
130
|
+
mock(del).invoke :delete_service, :service => service_2,
|
|
131
|
+
:really => true
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
subject
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context 'and the user answers no' do
|
|
139
|
+
it 'does not ask to delete orphaned serivces, or delete them' do
|
|
140
|
+
stub_ask("Really delete #{deleted_app.name}?", anything) { false }
|
|
141
|
+
dont_allow(deleted_app).delete!
|
|
142
|
+
|
|
143
|
+
stub(service_2).invalidate!
|
|
144
|
+
|
|
145
|
+
dont_allow_ask("Delete orphaned service #{service_2.name}?")
|
|
146
|
+
|
|
147
|
+
any_instance_of(VMC::App::Delete) do |del|
|
|
148
|
+
dont_allow(del).invoke(:delete_service, anything)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
subject
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context 'and --force is given' do
|
|
157
|
+
let(:global) { { :force => true, :color => false, :quiet => true } }
|
|
158
|
+
|
|
159
|
+
it 'does not delete orphaned services' do
|
|
160
|
+
dont_allow_ask
|
|
161
|
+
stub(deleted_app).delete!
|
|
162
|
+
|
|
163
|
+
any_instance_of(VMC::App::Delete) do |del|
|
|
164
|
+
dont_allow(del).invoke(:delete_service, anything)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
subject
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context 'and --delete-orphaned is given' do
|
|
172
|
+
let(:inputs) { { :app => deleted_app, :delete_orphaned => true } }
|
|
173
|
+
|
|
174
|
+
it 'deletes the orphaned services' do
|
|
175
|
+
stub_ask("Really delete #{deleted_app.name}?", anything) { true }
|
|
176
|
+
stub(deleted_app).delete!
|
|
177
|
+
|
|
178
|
+
any_instance_of(VMC::App::Delete) do |del|
|
|
179
|
+
mock(del).invoke :delete_service, :service => service_2,
|
|
180
|
+
:really => true
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
subject
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|