bosh_cli 0.16
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.
- data/README +4 -0
- data/Rakefile +55 -0
- data/bin/bosh +17 -0
- data/lib/cli.rb +76 -0
- data/lib/cli/cache.rb +44 -0
- data/lib/cli/changeset_helper.rb +142 -0
- data/lib/cli/command_definition.rb +52 -0
- data/lib/cli/commands/base.rb +245 -0
- data/lib/cli/commands/biff.rb +300 -0
- data/lib/cli/commands/blob.rb +125 -0
- data/lib/cli/commands/cloudcheck.rb +169 -0
- data/lib/cli/commands/deployment.rb +147 -0
- data/lib/cli/commands/job.rb +42 -0
- data/lib/cli/commands/job_management.rb +117 -0
- data/lib/cli/commands/log_management.rb +81 -0
- data/lib/cli/commands/maintenance.rb +131 -0
- data/lib/cli/commands/misc.rb +240 -0
- data/lib/cli/commands/package.rb +112 -0
- data/lib/cli/commands/property_management.rb +125 -0
- data/lib/cli/commands/release.rb +469 -0
- data/lib/cli/commands/ssh.rb +271 -0
- data/lib/cli/commands/stemcell.rb +184 -0
- data/lib/cli/commands/task.rb +213 -0
- data/lib/cli/commands/user.rb +28 -0
- data/lib/cli/commands/vms.rb +53 -0
- data/lib/cli/config.rb +154 -0
- data/lib/cli/core_ext.rb +145 -0
- data/lib/cli/dependency_helper.rb +62 -0
- data/lib/cli/deployment_helper.rb +263 -0
- data/lib/cli/deployment_manifest_compiler.rb +28 -0
- data/lib/cli/director.rb +633 -0
- data/lib/cli/director_task.rb +64 -0
- data/lib/cli/errors.rb +48 -0
- data/lib/cli/event_log_renderer.rb +351 -0
- data/lib/cli/job_builder.rb +226 -0
- data/lib/cli/package_builder.rb +254 -0
- data/lib/cli/packaging_helper.rb +248 -0
- data/lib/cli/release.rb +176 -0
- data/lib/cli/release_builder.rb +215 -0
- data/lib/cli/release_compiler.rb +178 -0
- data/lib/cli/release_tarball.rb +272 -0
- data/lib/cli/runner.rb +771 -0
- data/lib/cli/stemcell.rb +83 -0
- data/lib/cli/task_log_renderer.rb +40 -0
- data/lib/cli/templates/help_message.erb +75 -0
- data/lib/cli/validation.rb +42 -0
- data/lib/cli/version.rb +7 -0
- data/lib/cli/version_calc.rb +48 -0
- data/lib/cli/versions_index.rb +126 -0
- data/lib/cli/yaml_helper.rb +62 -0
- data/spec/assets/biff/bad_gateway_config.yml +28 -0
- data/spec/assets/biff/good_simple_config.yml +63 -0
- data/spec/assets/biff/good_simple_golden_config.yml +63 -0
- data/spec/assets/biff/good_simple_template.erb +69 -0
- data/spec/assets/biff/multiple_subnets_config.yml +40 -0
- data/spec/assets/biff/network_only_template.erb +34 -0
- data/spec/assets/biff/no_cc_config.yml +27 -0
- data/spec/assets/biff/no_range_config.yml +27 -0
- data/spec/assets/biff/no_subnet_config.yml +16 -0
- data/spec/assets/biff/ok_network_config.yml +30 -0
- data/spec/assets/biff/properties_template.erb +6 -0
- data/spec/assets/deployment.MF +0 -0
- data/spec/assets/plugins/bosh/cli/commands/echo.rb +43 -0
- data/spec/assets/plugins/bosh/cli/commands/ruby.rb +24 -0
- data/spec/assets/release/jobs/cacher.tgz +0 -0
- data/spec/assets/release/jobs/cacher/config/file1.conf +0 -0
- data/spec/assets/release/jobs/cacher/config/file2.conf +0 -0
- data/spec/assets/release/jobs/cacher/job.MF +6 -0
- data/spec/assets/release/jobs/cacher/monit +1 -0
- data/spec/assets/release/jobs/cleaner.tgz +0 -0
- data/spec/assets/release/jobs/cleaner/job.MF +4 -0
- data/spec/assets/release/jobs/cleaner/monit +1 -0
- data/spec/assets/release/jobs/sweeper.tgz +0 -0
- data/spec/assets/release/jobs/sweeper/config/test.conf +1 -0
- data/spec/assets/release/jobs/sweeper/job.MF +5 -0
- data/spec/assets/release/jobs/sweeper/monit +1 -0
- data/spec/assets/release/packages/mutator.tar.gz +0 -0
- data/spec/assets/release/packages/stuff.tgz +0 -0
- data/spec/assets/release/release.MF +17 -0
- data/spec/assets/release_invalid_checksum.tgz +0 -0
- data/spec/assets/release_invalid_jobs.tgz +0 -0
- data/spec/assets/release_no_name.tgz +0 -0
- data/spec/assets/release_no_version.tgz +0 -0
- data/spec/assets/stemcell/image +1 -0
- data/spec/assets/stemcell/stemcell.MF +6 -0
- data/spec/assets/stemcell_invalid_mf.tgz +0 -0
- data/spec/assets/stemcell_no_image.tgz +0 -0
- data/spec/assets/valid_release.tgz +0 -0
- data/spec/assets/valid_stemcell.tgz +0 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/unit/base_command_spec.rb +66 -0
- data/spec/unit/biff_spec.rb +135 -0
- data/spec/unit/cache_spec.rb +36 -0
- data/spec/unit/cli_commands_spec.rb +481 -0
- data/spec/unit/config_spec.rb +139 -0
- data/spec/unit/core_ext_spec.rb +77 -0
- data/spec/unit/dependency_helper_spec.rb +52 -0
- data/spec/unit/deployment_manifest_compiler_spec.rb +63 -0
- data/spec/unit/director_spec.rb +511 -0
- data/spec/unit/director_task_spec.rb +48 -0
- data/spec/unit/event_log_renderer_spec.rb +171 -0
- data/spec/unit/hash_changeset_spec.rb +73 -0
- data/spec/unit/job_builder_spec.rb +454 -0
- data/spec/unit/package_builder_spec.rb +567 -0
- data/spec/unit/release_builder_spec.rb +65 -0
- data/spec/unit/release_spec.rb +66 -0
- data/spec/unit/release_tarball_spec.rb +33 -0
- data/spec/unit/runner_spec.rb +140 -0
- data/spec/unit/ssh_spec.rb +78 -0
- data/spec/unit/stemcell_spec.rb +17 -0
- data/spec/unit/version_calc_spec.rb +27 -0
- data/spec/unit/versions_index_spec.rb +132 -0
- metadata +338 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Bosh::Cli::Command
|
|
2
|
+
class Ruby < Base
|
|
3
|
+
|
|
4
|
+
command :ruby_version do
|
|
5
|
+
usage "ruby version"
|
|
6
|
+
desc "Say ruby version"
|
|
7
|
+
route :ruby, :ruby_version
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
command :ruby_config do
|
|
11
|
+
usage "ruby config <string>"
|
|
12
|
+
desc "Query rbconfig"
|
|
13
|
+
route :ruby, :ruby_config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ruby_version
|
|
17
|
+
say(RUBY_VERSION)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def ruby_config(string)
|
|
21
|
+
say(::Config::CONFIG[string])
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Monit conf goes here
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Monit conf goes here
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
test
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Monit conf goes here
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: appcloud
|
|
3
|
+
version: 0.1
|
|
4
|
+
|
|
5
|
+
packages:
|
|
6
|
+
- name: stuff
|
|
7
|
+
version: 0.1.17
|
|
8
|
+
sha1: 6bbd4a12e3a59e10b96ecb9aac3d73ec4f819783
|
|
9
|
+
- name: mutator
|
|
10
|
+
version: 2.99.7
|
|
11
|
+
sha1: 86bd8b15562cde007f030a303fa64779af5fa4e7
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
- cacher
|
|
15
|
+
- cleaner
|
|
16
|
+
- sweeper
|
|
17
|
+
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
STEMCELL
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
require "rspec/core"
|
|
4
|
+
|
|
5
|
+
$:.unshift(File.expand_path("../../lib", __FILE__))
|
|
6
|
+
require "cli"
|
|
7
|
+
|
|
8
|
+
def spec_asset(filename)
|
|
9
|
+
File.expand_path(File.join(File.dirname(__FILE__), "assets", filename))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
tmpdir = Dir.mktmpdir
|
|
13
|
+
ENV["TMPDIR"] = tmpdir
|
|
14
|
+
FileUtils.mkdir_p(tmpdir)
|
|
15
|
+
at_exit { FileUtils.rm_rf(tmpdir) }
|
|
16
|
+
|
|
17
|
+
RSpec.configure do |c|
|
|
18
|
+
c.before(:each) do
|
|
19
|
+
Bosh::Cli::Config.interactive = false
|
|
20
|
+
Bosh::Cli::Config.colorize = false
|
|
21
|
+
Bosh::Cli::Config.output = StringIO.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
c.color_enabled = true
|
|
25
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Bosh::Cli::Command::Base do
|
|
6
|
+
|
|
7
|
+
before :each do
|
|
8
|
+
@config = File.join(Dir.mktmpdir, "bosh_config")
|
|
9
|
+
@cache_dir = Dir.mktmpdir
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def add_config(object)
|
|
13
|
+
File.open(@config, "w") do |f|
|
|
14
|
+
f.write(YAML.dump(object))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def make_command(options = { })
|
|
19
|
+
Bosh::Cli::Command::Base.new({ :config => @config,
|
|
20
|
+
:cache_dir => @cache_dir }.merge(options))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "can access configuration and respects options" do
|
|
24
|
+
add_config("target" => "localhost:8080", "deployment" => "test")
|
|
25
|
+
|
|
26
|
+
cmd = make_command(:verbose => true, :dry_run => true)
|
|
27
|
+
cmd.verbose?.should be_true
|
|
28
|
+
cmd.dry_run?.should be_true
|
|
29
|
+
cmd.target.should == "localhost:8080"
|
|
30
|
+
cmd.deployment.should == "test"
|
|
31
|
+
cmd.username.should == nil
|
|
32
|
+
cmd.password.should == nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "instantiates director when needed" do
|
|
36
|
+
add_config("target" => "localhost:8080", "deployment" => "test")
|
|
37
|
+
|
|
38
|
+
cmd = make_command()
|
|
39
|
+
cmd.director.director_uri.should == "localhost:8080"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "can evaluate other commands" do
|
|
43
|
+
cmd = make_command
|
|
44
|
+
new_cmd = mock(Object)
|
|
45
|
+
|
|
46
|
+
Bosh::Cli::Command::Misc.should_receive(:new).and_return(new_cmd)
|
|
47
|
+
new_cmd.should_receive(:status).with(:arg1, :arg2)
|
|
48
|
+
|
|
49
|
+
cmd.run("misc", "status", :arg1, :arg2)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "can redirect to other commands " +
|
|
53
|
+
"(effectively exiting after running them)" do
|
|
54
|
+
cmd = make_command
|
|
55
|
+
new_cmd = mock(Object)
|
|
56
|
+
|
|
57
|
+
Bosh::Cli::Command::Misc.should_receive(:new).and_return(new_cmd)
|
|
58
|
+
new_cmd.should_receive(:status).with(:arg1, :arg2)
|
|
59
|
+
|
|
60
|
+
lambda {
|
|
61
|
+
cmd.redirect("misc", "status", :arg1, :arg2)
|
|
62
|
+
}.should raise_error(Bosh::Cli::GracefulExit,
|
|
63
|
+
"redirected to misc status arg1 arg2")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Bosh::Cli::Command::Biff do
|
|
4
|
+
|
|
5
|
+
before :each do
|
|
6
|
+
# Let us test all private methods.
|
|
7
|
+
Bosh::Cli::Command::Biff.send(:public,
|
|
8
|
+
*Bosh::Cli::Command::Biff.private_instance_methods)
|
|
9
|
+
@biff = Bosh::Cli::Command::Biff.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
after :each do
|
|
13
|
+
@biff.delete_temp_diff_files
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "throws an error when there is more than one subnet for default" do
|
|
17
|
+
config_file = spec_asset("biff/multiple_subnets_config.yml")
|
|
18
|
+
template_file = spec_asset("biff/network_only_template.erb")
|
|
19
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
20
|
+
lambda {
|
|
21
|
+
@biff.biff(template_file)
|
|
22
|
+
}.should raise_error(RuntimeError, "Biff doesn't know how to deal with " +
|
|
23
|
+
"anything other than one subnet in default")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "throws an error when the gateway is anything other than the first ip" do
|
|
27
|
+
config_file = spec_asset("biff/bad_gateway_config.yml")
|
|
28
|
+
template_file = spec_asset("biff/network_only_template.erb")
|
|
29
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
30
|
+
lambda {
|
|
31
|
+
@biff.biff(template_file)
|
|
32
|
+
}.should raise_error(RuntimeError, "Biff only supports configurations " +
|
|
33
|
+
"where the gateway is the first IP (e.g. 172.31.196.1).")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "throws an error when the range is not specified in the config" do
|
|
37
|
+
config_file = spec_asset("biff/no_range_config.yml")
|
|
38
|
+
template_file = spec_asset("biff/network_only_template.erb")
|
|
39
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
40
|
+
lambda {
|
|
41
|
+
@biff.biff(template_file)
|
|
42
|
+
}.should raise_error(RuntimeError, "Biff requires each network to have " +
|
|
43
|
+
"range and dns entries.")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "throws an error if there are no subnets" do
|
|
47
|
+
config_file = spec_asset("biff/no_subnet_config.yml")
|
|
48
|
+
template_file = spec_asset("biff/network_only_template.erb")
|
|
49
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
50
|
+
lambda {
|
|
51
|
+
@biff.biff(template_file)
|
|
52
|
+
}.should raise_error(RuntimeError, "You must have subnets in default")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "outputs the required yaml when the input does not contain it" do
|
|
56
|
+
config_file = spec_asset("biff/no_cc_config.yml")
|
|
57
|
+
template_file = spec_asset("biff/properties_template.erb")
|
|
58
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
59
|
+
|
|
60
|
+
@biff.should_receive(:say).with(
|
|
61
|
+
"Could not find properties.cc.srv_api_uri.").once
|
|
62
|
+
|
|
63
|
+
@biff.should_receive(:say).with("'#{template_file}' has it but " +
|
|
64
|
+
"'#{config_file}' does not.").once
|
|
65
|
+
|
|
66
|
+
# Cannot use this because 1.8.7 does not preserve Hash order, so this string
|
|
67
|
+
# can come back in any order.
|
|
68
|
+
@biff.should_receive(:say).with(/Add this to '':/).once
|
|
69
|
+
|
|
70
|
+
#@biff.should_receive(:say).once
|
|
71
|
+
|
|
72
|
+
@biff.should_receive(:say).with("There were 1 errors.").once
|
|
73
|
+
|
|
74
|
+
@biff.biff(template_file)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "correctly generates a file and reports when there are no differences" do
|
|
78
|
+
config_file = spec_asset("biff/good_simple_config.yml")
|
|
79
|
+
template_file = spec_asset("biff/good_simple_template.erb")
|
|
80
|
+
golden_file = spec_asset("biff/good_simple_golden_config.yml")
|
|
81
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
82
|
+
@biff.should_receive(:say).with("No differences.").once
|
|
83
|
+
|
|
84
|
+
@biff.biff(template_file)
|
|
85
|
+
@biff.template_output.should == File.read(golden_file)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "asks whether you would like to keep the new file" do
|
|
89
|
+
config_file = spec_asset("biff/ok_network_config.yml")
|
|
90
|
+
template_file = spec_asset("biff/network_only_template.erb")
|
|
91
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
92
|
+
@biff.should_receive(:agree).with(
|
|
93
|
+
"Would you like to keep the new version? [yn]").once.and_return(false)
|
|
94
|
+
|
|
95
|
+
@biff.biff(template_file)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "deletes temporary files" do
|
|
99
|
+
config_file = spec_asset("biff/ok_network_config.yml")
|
|
100
|
+
template_file = spec_asset("biff/network_only_template.erb")
|
|
101
|
+
@biff.stub!(:deployment).and_return(config_file)
|
|
102
|
+
@biff.should_receive(:agree).and_return(false)
|
|
103
|
+
# Twice because of after :each
|
|
104
|
+
@biff.should_receive(:delete_temp_diff_files).twice
|
|
105
|
+
@biff.biff(template_file)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "finds the object path" do
|
|
109
|
+
obj = { "path1" => {"path2" => {"path3" => 3}} }
|
|
110
|
+
@biff.find_in("path1.path2.path3", obj).should == 3
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "finds the object path in an array by the name key" do
|
|
114
|
+
obj = { "by_key" => 1, "arr" => [{"name" => "by_name"}]}
|
|
115
|
+
@biff.find_in("arr.by_name", obj).should == {"name" => "by_name"}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "allows ip_range to take negative ranges" do
|
|
119
|
+
@biff.ip_helper = {
|
|
120
|
+
"default" => NetAddr::CIDR.create("192.168.1.0/22")
|
|
121
|
+
}
|
|
122
|
+
@biff.ip_range(-11..-2, "default").should == "192.168.3.245 - 192.168.3.254"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "deletes all except one entry from a Hash" do
|
|
126
|
+
obj = { "by_key" => 1, "arr" => [{"name" => "by_name"}]}
|
|
127
|
+
@biff.delete_all_except(obj, "by_key").should == { "by_key" => 1 }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "deletes all except one entry from a Array" do
|
|
131
|
+
obj = [ {"name" => "a"}, {"name" => "b"}, {"name" => "c"}]
|
|
132
|
+
@biff.delete_all_except(obj, "b").should == [ {"name" => "b"} ]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
|
|
6
|
+
describe Bosh::Cli::Cache do
|
|
7
|
+
|
|
8
|
+
before :each do
|
|
9
|
+
@cache_dir = File.join(Dir.mktmpdir, "bosh_cache")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
after :each do
|
|
13
|
+
FileUtils.rm_rf(@cache_dir)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "whines if cache directory turned out to be a file" do
|
|
17
|
+
FileUtils.touch(@cache_dir)
|
|
18
|
+
lambda {
|
|
19
|
+
Bosh::Cli::Cache.new(@cache_dir)
|
|
20
|
+
}.should raise_error(Bosh::Cli::CacheDirectoryError)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "creates cache directory" do
|
|
24
|
+
File.directory?(@cache_dir).should be_false
|
|
25
|
+
cache = Bosh::Cli::Cache.new(@cache_dir)
|
|
26
|
+
File.directory?(@cache_dir).should be_true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "performs read/write in an expected way" do
|
|
30
|
+
cache = Bosh::Cli::Cache.new(@cache_dir)
|
|
31
|
+
cache.read("foo").should be_nil
|
|
32
|
+
cache.write("foo", "12321")
|
|
33
|
+
cache.read("foo").should == "12321"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Bosh::Cli::Command::Base do
|
|
6
|
+
|
|
7
|
+
before :each do
|
|
8
|
+
@config = File.join(Dir.mktmpdir, "bosh_config")
|
|
9
|
+
@cache = File.join(Dir.mktmpdir, "bosh_cache")
|
|
10
|
+
@opts = { :config => @config, :cache_dir => @cache }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe Bosh::Cli::Command::Misc do
|
|
14
|
+
|
|
15
|
+
before :each do
|
|
16
|
+
@cmd = Bosh::Cli::Command::Misc.new(@opts)
|
|
17
|
+
@cmd.stub!(:interactive?).and_return(false)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "sets the target" do
|
|
21
|
+
@cmd.target.should == nil
|
|
22
|
+
@cmd.set_target("http://example.com:232")
|
|
23
|
+
@cmd.target.should == "http://example.com:232"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "normalizes target" do
|
|
27
|
+
@cmd.target.should == nil
|
|
28
|
+
@cmd.set_target("test")
|
|
29
|
+
@cmd.target.should == "http://test"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "respects director checks option when setting target" do
|
|
33
|
+
@cmd.options[:director_checks] = true
|
|
34
|
+
|
|
35
|
+
lambda {
|
|
36
|
+
mock_director = mock(Object)
|
|
37
|
+
mock_director.stub!(:get_status).and_raise(Bosh::Cli::DirectorError)
|
|
38
|
+
Bosh::Cli::Director.should_receive(:new).
|
|
39
|
+
with("http://test").and_return(mock_director)
|
|
40
|
+
@cmd.set_target("test")
|
|
41
|
+
}.should raise_error(Bosh::Cli::CliExit,
|
|
42
|
+
"Cannot talk to director at 'http://test', " +
|
|
43
|
+
"please set correct target")
|
|
44
|
+
|
|
45
|
+
@cmd.target.should == nil
|
|
46
|
+
|
|
47
|
+
mock_director = mock(Object)
|
|
48
|
+
mock_director.stub!(:get_status).and_return("name" => "ZB")
|
|
49
|
+
Bosh::Cli::Director.should_receive(:new).
|
|
50
|
+
with("http://test").and_return(mock_director)
|
|
51
|
+
@cmd.set_target("test")
|
|
52
|
+
@cmd.target.should == "http://test"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "supports named targets" do
|
|
56
|
+
@cmd.set_target("test", "mytarget")
|
|
57
|
+
@cmd.target.should == "http://test"
|
|
58
|
+
|
|
59
|
+
@cmd.set_target("foo", "myfoo")
|
|
60
|
+
|
|
61
|
+
@cmd.set_target("mytarget")
|
|
62
|
+
@cmd.target.should == "http://test"
|
|
63
|
+
|
|
64
|
+
@cmd.set_target("myfoo")
|
|
65
|
+
@cmd.target.should == "http://foo"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "logs user in" do
|
|
69
|
+
@cmd.set_target("test")
|
|
70
|
+
@cmd.login("user", "pass")
|
|
71
|
+
@cmd.logged_in?.should be_true
|
|
72
|
+
@cmd.username.should == "user"
|
|
73
|
+
@cmd.password.should == "pass"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "logs user out" do
|
|
77
|
+
@cmd.set_target("test")
|
|
78
|
+
@cmd.login("user", "pass")
|
|
79
|
+
@cmd.logout
|
|
80
|
+
@cmd.logged_in?.should be_false
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "respects director checks option when logging in" do
|
|
84
|
+
@cmd.options[:director_checks] = true
|
|
85
|
+
|
|
86
|
+
mock_director = mock(Object)
|
|
87
|
+
mock_director.stub(:get_status).
|
|
88
|
+
and_return({ "user" => "user", "name" => "ZB" })
|
|
89
|
+
mock_director.stub(:authenticated?).and_return(true)
|
|
90
|
+
|
|
91
|
+
Bosh::Cli::Director.should_receive(:new).
|
|
92
|
+
with("http://test").and_return(mock_director)
|
|
93
|
+
@cmd.set_target("test")
|
|
94
|
+
|
|
95
|
+
Bosh::Cli::Director.should_receive(:new).
|
|
96
|
+
with("http://test", "user", "pass").and_return(mock_director)
|
|
97
|
+
|
|
98
|
+
@cmd.login("user", "pass")
|
|
99
|
+
@cmd.logged_in?.should be_true
|
|
100
|
+
@cmd.username.should == "user"
|
|
101
|
+
@cmd.password.should == "pass"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe Bosh::Cli::Command::Stemcell do
|
|
106
|
+
before :each do
|
|
107
|
+
@cmd = Bosh::Cli::Command::Stemcell.new(@opts)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "allows deleting the stemcell" do
|
|
111
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
112
|
+
mock_director.should_receive(:delete_stemcell).with("foo", "123")
|
|
113
|
+
|
|
114
|
+
@cmd.stub!(:interactive?).and_return(false)
|
|
115
|
+
@cmd.stub!(:target).and_return("test")
|
|
116
|
+
@cmd.stub!(:username).and_return("user")
|
|
117
|
+
@cmd.stub!(:password).and_return("pass")
|
|
118
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
119
|
+
@cmd.delete("foo", "123")
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "needs confirmation to delete stemcell" do
|
|
123
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
124
|
+
mock_director.should_not_receive(:delete_stemcell)
|
|
125
|
+
|
|
126
|
+
@cmd.stub!(:target).and_return("test")
|
|
127
|
+
@cmd.stub!(:username).and_return("user")
|
|
128
|
+
@cmd.stub!(:password).and_return("pass")
|
|
129
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
130
|
+
@cmd.stub!(:ask).and_return("")
|
|
131
|
+
@cmd.delete("foo", "123")
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe Bosh::Cli::Command::Deployment do
|
|
136
|
+
before :each do
|
|
137
|
+
@cmd = Bosh::Cli::Command::Deployment.new(@opts)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "allows deleting the deployment" do
|
|
141
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
142
|
+
mock_director.should_receive(:delete_deployment).
|
|
143
|
+
with("foo", :force => false)
|
|
144
|
+
|
|
145
|
+
@cmd.stub!(:interactive?).and_return(false)
|
|
146
|
+
@cmd.stub!(:target).and_return("test")
|
|
147
|
+
@cmd.stub!(:username).and_return("user")
|
|
148
|
+
@cmd.stub!(:password).and_return("pass")
|
|
149
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
150
|
+
@cmd.delete("foo")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "needs confirmation to delete deployment" do
|
|
154
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
155
|
+
mock_director.should_not_receive(:delete_deployment)
|
|
156
|
+
|
|
157
|
+
@cmd.stub!(:target).and_return("test")
|
|
158
|
+
@cmd.stub!(:username).and_return("user")
|
|
159
|
+
@cmd.stub!(:password).and_return("pass")
|
|
160
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
161
|
+
@cmd.stub!(:ask).and_return("")
|
|
162
|
+
@cmd.delete("foo")
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
describe Bosh::Cli::Command::Release do
|
|
167
|
+
before :each do
|
|
168
|
+
@cmd = Bosh::Cli::Command::Release.new(@opts)
|
|
169
|
+
@cmd.stub!(:target).and_return("test")
|
|
170
|
+
@cmd.stub!(:username).and_return("user")
|
|
171
|
+
@cmd.stub!(:password).and_return("pass")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "allows deleting the release (non-force)" do
|
|
175
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
176
|
+
mock_director.should_receive(:delete_release).
|
|
177
|
+
with("foo", :force => false, :version => nil)
|
|
178
|
+
|
|
179
|
+
@cmd.stub!(:interactive?).and_return(false)
|
|
180
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
181
|
+
@cmd.delete("foo")
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "allows deleting the release (non-force)" do
|
|
185
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
186
|
+
mock_director.should_receive(:delete_release).
|
|
187
|
+
with("foo", :force => true, :version => nil)
|
|
188
|
+
|
|
189
|
+
@cmd.stub!(:ask).and_return("yes")
|
|
190
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
191
|
+
@cmd.delete("foo", "--force")
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "allows deleting a particular release version (non-force)" do
|
|
195
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
196
|
+
mock_director.should_receive(:delete_release).
|
|
197
|
+
with("foo", :force => false, :version => "42")
|
|
198
|
+
|
|
199
|
+
@cmd.stub!(:ask).and_return("yes")
|
|
200
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
201
|
+
@cmd.delete("foo", "42")
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "allows deleting a particular release version (non-force)" do
|
|
205
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
206
|
+
mock_director.should_receive(:delete_release).
|
|
207
|
+
with("foo", :force => true, :version => "42")
|
|
208
|
+
|
|
209
|
+
@cmd.stub!(:ask).and_return("yes")
|
|
210
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
211
|
+
@cmd.delete("foo", "42", "--force")
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "requires confirmation on deleting release" do
|
|
215
|
+
mock_director = mock(Bosh::Cli::Director)
|
|
216
|
+
mock_director.should_not_receive(:delete_release)
|
|
217
|
+
@cmd.stub!(:director).and_return(mock_director)
|
|
218
|
+
@cmd.stub!(:ask).and_return("")
|
|
219
|
+
@cmd.delete("foo")
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe Bosh::Cli::Command::JobManagement do
|
|
225
|
+
before :each do
|
|
226
|
+
@manifest_path = spec_asset("deployment.MF")
|
|
227
|
+
@manifest_yaml = YAML.dump({ "name" => "foo" })
|
|
228
|
+
@cmd = Bosh::Cli::Command::JobManagement.new(@opts)
|
|
229
|
+
@cmd.stub!(:prepare_deployment_manifest).
|
|
230
|
+
with(:yaml => true).and_return(@manifest_yaml)
|
|
231
|
+
@cmd.stub!(:interactive?).and_return(false)
|
|
232
|
+
@cmd.stub!(:deployment).and_return(@manifest_path)
|
|
233
|
+
@cmd.stub!(:target).and_return("test.com")
|
|
234
|
+
@cmd.stub!(:target_name).and_return("dev2")
|
|
235
|
+
@cmd.stub!(:username).and_return("user")
|
|
236
|
+
@cmd.stub!(:password).and_return("pass")
|
|
237
|
+
@director = mock(Bosh::Cli::Director)
|
|
238
|
+
@cmd.stub!(:director).and_return(@director)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it "allows starting jobs" do
|
|
242
|
+
@director.should_receive(:change_job_state).
|
|
243
|
+
with("foo", @manifest_yaml, "dea", nil, "started")
|
|
244
|
+
@cmd.start_job("dea")
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it "allows starting job instances" do
|
|
248
|
+
@director.should_receive(:change_job_state).
|
|
249
|
+
with("foo", @manifest_yaml, "dea", 3, "started")
|
|
250
|
+
@cmd.start_job("dea", 3)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it "allows stopping jobs" do
|
|
254
|
+
@director.should_receive(:change_job_state).
|
|
255
|
+
with("foo", @manifest_yaml, "dea", nil, "stopped")
|
|
256
|
+
@cmd.stop_job("dea")
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it "allows stopping job instances" do
|
|
260
|
+
@director.should_receive(:change_job_state).
|
|
261
|
+
with("foo", @manifest_yaml, "dea", 3, "stopped")
|
|
262
|
+
@cmd.stop_job("dea", 3)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it "allows restarting jobs" do
|
|
266
|
+
@director.should_receive(:change_job_state).
|
|
267
|
+
with("foo", @manifest_yaml, "dea", nil, "restart")
|
|
268
|
+
@cmd.restart_job("dea")
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "allows restart job instances" do
|
|
272
|
+
@director.should_receive(:change_job_state).
|
|
273
|
+
with("foo", @manifest_yaml, "dea", 3, "restart")
|
|
274
|
+
@cmd.restart_job("dea", 3)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "allows recreating jobs" do
|
|
278
|
+
@director.should_receive(:change_job_state).
|
|
279
|
+
with("foo", @manifest_yaml, "dea", nil, "recreate")
|
|
280
|
+
@cmd.recreate_job("dea")
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it "allows recreating job instances" do
|
|
284
|
+
@director.should_receive(:change_job_state).
|
|
285
|
+
with("foo", @manifest_yaml, "dea", 3, "recreate")
|
|
286
|
+
@cmd.recreate_job("dea", 3)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "allows hard stop" do
|
|
290
|
+
@director.should_receive(:change_job_state).
|
|
291
|
+
with("foo", @manifest_yaml, "dea", 3, "detached")
|
|
292
|
+
@cmd.stop_job("dea", 3, "--hard")
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it "allows soft stop (= regular stop)" do
|
|
296
|
+
@director.should_receive(:change_job_state).
|
|
297
|
+
with("foo", @manifest_yaml, "dea", 3, "stopped")
|
|
298
|
+
@cmd.stop_job("dea", 3, "--soft")
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
describe Bosh::Cli::Command::Blob do
|
|
304
|
+
before :each do
|
|
305
|
+
@cmd = Bosh::Cli::Command::Blob.new(@opts)
|
|
306
|
+
@release_dir = Dir.mktmpdir
|
|
307
|
+
@blob_dir = File.join(@release_dir, "blobs/")
|
|
308
|
+
@cmd.stub!(:work_dir).and_return(@release_dir)
|
|
309
|
+
@blobstore = mock("blobstore")
|
|
310
|
+
@cmd.stub!(:blobstore).and_return(@blobstore)
|
|
311
|
+
FileUtils.mkdir(@blob_dir)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
after :each do
|
|
315
|
+
FileUtils.rm_rf(@release_dir)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "refuse to run outside of the release directory" do
|
|
319
|
+
lambda {
|
|
320
|
+
@cmd.upload_blob("foo")
|
|
321
|
+
}.should raise_error(Bosh::Cli::CliExit,
|
|
322
|
+
"Sorry, your current directory doesn't " +
|
|
323
|
+
"look like release directory".red)
|
|
324
|
+
|
|
325
|
+
lambda {
|
|
326
|
+
@cmd.sync_blobs
|
|
327
|
+
}.should raise_error(Bosh::Cli::CliExit,
|
|
328
|
+
"Sorry, your current directory doesn't " +
|
|
329
|
+
"look like release directory".red)
|
|
330
|
+
|
|
331
|
+
lambda {
|
|
332
|
+
@cmd.blobs_info
|
|
333
|
+
}.should raise_error(Bosh::Cli::CliExit,
|
|
334
|
+
"Sorry, your current directory doesn't " +
|
|
335
|
+
"look like release directory".red)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it "refuse to upload blob outside of release/blobs" do
|
|
339
|
+
Dir.chdir(@release_dir) do
|
|
340
|
+
FileUtils.touch("test.tgz")
|
|
341
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
342
|
+
blob_path = Pathname.new(@release_dir).realpath.to_s
|
|
343
|
+
blobs_dir = Pathname.new(@blob_dir).realpath.to_s
|
|
344
|
+
lambda {
|
|
345
|
+
@cmd.upload_blob("test.tgz")
|
|
346
|
+
}.should raise_error(Bosh::Cli::CliExit,
|
|
347
|
+
"#{File.join(blob_path, "test.tgz")} is " +
|
|
348
|
+
"NOT under #{blobs_dir}/")
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it "upload new blob to blobstore" do
|
|
353
|
+
Dir.chdir(@release_dir) do
|
|
354
|
+
FileUtils.mkdir("./blobs/test")
|
|
355
|
+
blob = FileUtils.touch("./blobs/test/test.tgz")
|
|
356
|
+
@cmd.should_receive(:get_blobs_index).and_return({})
|
|
357
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
358
|
+
@blobstore.should_receive(:create).and_return(2)
|
|
359
|
+
@cmd.upload_blob("./blobs/test/test.tgz")
|
|
360
|
+
YAML.load_file("blob_index.yml").should == {
|
|
361
|
+
"test/test.tgz" => {
|
|
362
|
+
"object_id" => 2,
|
|
363
|
+
"sha" => Digest::SHA1.file(blob.first).hexdigest
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "should skip upload if blob already exists" do
|
|
370
|
+
Dir.chdir(@release_dir) do
|
|
371
|
+
FileUtils.mkdir("./blobs/test")
|
|
372
|
+
blob = FileUtils.touch("./blobs/test/test.tgz")
|
|
373
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
374
|
+
@cmd.should_receive(:get_blobs_index).and_return('test/test.tgz' => {
|
|
375
|
+
"sha" => Digest::SHA1.file(blob.first).hexdigest,
|
|
376
|
+
"object_id" => 2
|
|
377
|
+
})
|
|
378
|
+
@blobstore.should_not_receive(:create)
|
|
379
|
+
@cmd.upload_blob("./blobs/test/test.tgz")
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it "should ask user if blob was modified" do
|
|
384
|
+
Dir.chdir(@release_dir) do
|
|
385
|
+
FileUtils.mkdir("./blobs/test")
|
|
386
|
+
blob = FileUtils.touch("./blobs/test/test.tgz")
|
|
387
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
388
|
+
@cmd.should_receive(:get_blobs_index).and_return('test/test.tgz' => {
|
|
389
|
+
"sha" => 1,
|
|
390
|
+
"object_id" => 2
|
|
391
|
+
})
|
|
392
|
+
@cmd.should_receive(:ask).and_return("no")
|
|
393
|
+
@blobstore.should_not_receive(:create)
|
|
394
|
+
@cmd.upload_blob("./blobs/test/test.tgz")
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it "should sync if file is not present" do
|
|
399
|
+
Dir.chdir(@release_dir) do
|
|
400
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
401
|
+
@cmd.should_receive(:get_blobs_index).and_return('test/test.tgz' => {
|
|
402
|
+
"sha" => 1,
|
|
403
|
+
"object_id" => 2
|
|
404
|
+
})
|
|
405
|
+
@cmd.should_receive(:fetch_blob).
|
|
406
|
+
with(File.join(@release_dir, "blobs", "test/test.tgz"),
|
|
407
|
+
{ "sha" => 1, "object_id" => 2 })
|
|
408
|
+
@cmd.sync_blobs
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "should not sync if the same file is present" do
|
|
413
|
+
Dir.chdir(@release_dir) do
|
|
414
|
+
FileUtils.mkdir("./blobs/test")
|
|
415
|
+
blob = FileUtils.touch("./blobs/test/test.tgz")
|
|
416
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
417
|
+
@cmd.should_receive(:get_blobs_index).and_return('test/test.tgz' => {
|
|
418
|
+
"sha" => Digest::SHA1.file(blob.first).hexdigest,
|
|
419
|
+
"object_id" => 2
|
|
420
|
+
})
|
|
421
|
+
@cmd.should_not_receive(:fetch_blob)
|
|
422
|
+
@cmd.sync_blobs
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
it "should ask user if blob sha is different" do
|
|
427
|
+
Dir.chdir(@release_dir) do
|
|
428
|
+
FileUtils.mkdir("./blobs/test")
|
|
429
|
+
blob = FileUtils.touch("./blobs/test/test.tgz")
|
|
430
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
431
|
+
@cmd.should_receive(:get_blobs_index).and_return('test/test.tgz' => {
|
|
432
|
+
"sha" => 1,
|
|
433
|
+
"object_id" => 2
|
|
434
|
+
})
|
|
435
|
+
@cmd.should_receive(:ask).and_return("")
|
|
436
|
+
@cmd.should_not_receive(:fetch_blob)
|
|
437
|
+
@cmd.sync_blobs
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "reports untracked blobs" do
|
|
442
|
+
Dir.chdir(@release_dir) do
|
|
443
|
+
FileUtils.mkdir("./blobs/test")
|
|
444
|
+
FileUtils.touch("./blobs/test/test.tgz")
|
|
445
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
446
|
+
@cmd.should_receive(:get_blobs_index).and_return({})
|
|
447
|
+
@cmd.should_receive(:say).
|
|
448
|
+
with("\nNew blobs ('bosh upload blob' to add): ".green)
|
|
449
|
+
@cmd.should_receive(:say).with("test/test.tgz")
|
|
450
|
+
@cmd.blobs_info
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
it "reports modified blobs" do
|
|
455
|
+
Dir.chdir(@release_dir) do
|
|
456
|
+
FileUtils.mkdir("./blobs/test")
|
|
457
|
+
FileUtils.touch("./blobs/test/test.tgz")
|
|
458
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
459
|
+
@cmd.should_receive(:get_blobs_index).
|
|
460
|
+
and_return({ "test/test.tgz" => { "sha" => 1, "object_id" => 2}})
|
|
461
|
+
@cmd.should_receive(:say).
|
|
462
|
+
with("\nModified blobs ('bosh upload blob' to update): ".green)
|
|
463
|
+
@cmd.should_receive(:say).with("test/test.tgz")
|
|
464
|
+
@cmd.blobs_info
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
it "reports unsynced blobs" do
|
|
469
|
+
Dir.chdir(@release_dir) do
|
|
470
|
+
@cmd.should_receive(:check_if_blobs_supported).and_return(true)
|
|
471
|
+
@cmd.should_receive(:get_blobs_index).
|
|
472
|
+
and_return({ "test/test.tgz" => { "sha" => 1, "object_id" => 2}})
|
|
473
|
+
@cmd.should_receive(:say).
|
|
474
|
+
with("\nMissing blobs ('bosh sync blobs' to fetch) : ".green)
|
|
475
|
+
@cmd.should_receive(:say).with("test/test.tgz")
|
|
476
|
+
@cmd.blobs_info
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
end
|