bosh_cli 1.0.3 → 1.5.0.pre.1113

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 (144) hide show
  1. data/bin/bosh +0 -9
  2. data/lib/cli.rb +69 -64
  3. data/lib/cli/backup_destination_path.rb +33 -0
  4. data/lib/cli/base_command.rb +57 -56
  5. data/lib/cli/blob_manager.rb +12 -12
  6. data/lib/cli/changeset_helper.rb +6 -7
  7. data/lib/cli/client/director.rb +724 -0
  8. data/lib/cli/command_handler.rb +6 -7
  9. data/lib/cli/commands/backup.rb +39 -0
  10. data/lib/cli/commands/biff.rb +42 -21
  11. data/lib/cli/commands/blob_management.rb +1 -1
  12. data/lib/cli/commands/cloudcheck.rb +11 -13
  13. data/lib/cli/commands/deployment.rb +53 -37
  14. data/lib/cli/commands/help.rb +3 -2
  15. data/lib/cli/commands/job_management.rb +67 -103
  16. data/lib/cli/commands/job_rename.rb +6 -8
  17. data/lib/cli/commands/log_management.rb +78 -55
  18. data/lib/cli/commands/maintenance.rb +36 -30
  19. data/lib/cli/commands/misc.rb +72 -51
  20. data/lib/cli/commands/package.rb +2 -2
  21. data/lib/cli/commands/property_management.rb +10 -12
  22. data/lib/cli/commands/release.rb +236 -133
  23. data/lib/cli/commands/snapshot.rb +93 -0
  24. data/lib/cli/commands/ssh.rb +216 -213
  25. data/lib/cli/commands/stemcell.rb +46 -34
  26. data/lib/cli/commands/task.rb +2 -2
  27. data/lib/cli/commands/user.rb +27 -3
  28. data/lib/cli/commands/vm.rb +28 -0
  29. data/lib/cli/commands/vms.rb +81 -23
  30. data/lib/cli/config.rb +6 -2
  31. data/lib/cli/core_ext.rb +31 -30
  32. data/lib/cli/deployment_helper.rb +134 -159
  33. data/lib/cli/deployment_manifest.rb +66 -0
  34. data/lib/cli/deployment_manifest_compiler.rb +0 -3
  35. data/lib/cli/event_log_renderer.rb +10 -10
  36. data/lib/cli/file_with_progress_bar.rb +52 -0
  37. data/lib/cli/job_builder.rb +1 -1
  38. data/lib/cli/job_command_args.rb +23 -0
  39. data/lib/cli/job_property_collection.rb +4 -7
  40. data/lib/cli/job_property_validator.rb +22 -12
  41. data/lib/cli/job_state.rb +54 -0
  42. data/lib/cli/line_wrap.rb +54 -0
  43. data/lib/cli/packaging_helper.rb +10 -10
  44. data/lib/cli/release.rb +18 -15
  45. data/lib/cli/release_builder.rb +9 -4
  46. data/lib/cli/release_compiler.rb +9 -9
  47. data/lib/cli/release_tarball.rb +3 -6
  48. data/lib/cli/resurrection.rb +31 -0
  49. data/lib/cli/runner.rb +56 -30
  50. data/lib/cli/stemcell.rb +25 -10
  51. data/lib/cli/task_log_renderer.rb +1 -1
  52. data/lib/cli/task_tracker.rb +10 -9
  53. data/lib/cli/validation.rb +3 -1
  54. data/lib/cli/version.rb +1 -1
  55. data/lib/cli/version_calc.rb +5 -18
  56. data/lib/cli/versions_index.rb +1 -1
  57. data/lib/cli/vm_state.rb +43 -0
  58. data/lib/cli/yaml_helper.rb +26 -35
  59. metadata +75 -208
  60. data/Rakefile +0 -56
  61. data/lib/cli/director.rb +0 -628
  62. data/spec/assets/biff/bad_gateway_config.yml +0 -28
  63. data/spec/assets/biff/good_simple_config.yml +0 -63
  64. data/spec/assets/biff/good_simple_golden_config.yml +0 -63
  65. data/spec/assets/biff/good_simple_template.erb +0 -69
  66. data/spec/assets/biff/ip_out_of_range.yml +0 -63
  67. data/spec/assets/biff/multiple_subnets_config.yml +0 -40
  68. data/spec/assets/biff/network_only_template.erb +0 -34
  69. data/spec/assets/biff/no_cc_config.yml +0 -27
  70. data/spec/assets/biff/no_range_config.yml +0 -27
  71. data/spec/assets/biff/no_subnet_config.yml +0 -16
  72. data/spec/assets/biff/ok_network_config.yml +0 -30
  73. data/spec/assets/biff/properties_template.erb +0 -6
  74. data/spec/assets/config/atmos/config/final.yml +0 -6
  75. data/spec/assets/config/atmos/config/private.yml +0 -4
  76. data/spec/assets/config/bad-providers/config/final.yml +0 -5
  77. data/spec/assets/config/bad-providers/config/private.yml +0 -4
  78. data/spec/assets/config/deprecation/config/final.yml +0 -5
  79. data/spec/assets/config/deprecation/config/private.yml +0 -2
  80. data/spec/assets/config/local/config/final.yml +0 -5
  81. data/spec/assets/config/local/config/private.yml +0 -1
  82. data/spec/assets/config/s3/config/final.yml +0 -5
  83. data/spec/assets/config/s3/config/private.yml +0 -5
  84. data/spec/assets/config/swift-hp/config/final.yml +0 -6
  85. data/spec/assets/config/swift-hp/config/private.yml +0 -7
  86. data/spec/assets/config/swift-rackspace/config/final.yml +0 -6
  87. data/spec/assets/config/swift-rackspace/config/private.yml +0 -6
  88. data/spec/assets/deployment.MF +0 -0
  89. data/spec/assets/plugins/bosh/cli/commands/echo.rb +0 -43
  90. data/spec/assets/plugins/bosh/cli/commands/ruby.rb +0 -24
  91. data/spec/assets/release/jobs/cacher.tgz +0 -0
  92. data/spec/assets/release/jobs/cacher/config/file1.conf +0 -0
  93. data/spec/assets/release/jobs/cacher/config/file2.conf +0 -0
  94. data/spec/assets/release/jobs/cacher/job.MF +0 -6
  95. data/spec/assets/release/jobs/cacher/monit +0 -1
  96. data/spec/assets/release/jobs/cleaner.tgz +0 -0
  97. data/spec/assets/release/jobs/cleaner/job.MF +0 -4
  98. data/spec/assets/release/jobs/cleaner/monit +0 -1
  99. data/spec/assets/release/jobs/sweeper.tgz +0 -0
  100. data/spec/assets/release/jobs/sweeper/config/test.conf +0 -1
  101. data/spec/assets/release/jobs/sweeper/job.MF +0 -5
  102. data/spec/assets/release/jobs/sweeper/monit +0 -1
  103. data/spec/assets/release/packages/mutator.tar.gz +0 -0
  104. data/spec/assets/release/packages/stuff.tgz +0 -0
  105. data/spec/assets/release/release.MF +0 -17
  106. data/spec/assets/release_invalid_checksum.tgz +0 -0
  107. data/spec/assets/release_invalid_jobs.tgz +0 -0
  108. data/spec/assets/release_no_name.tgz +0 -0
  109. data/spec/assets/release_no_version.tgz +0 -0
  110. data/spec/assets/stemcell/image +0 -1
  111. data/spec/assets/stemcell/stemcell.MF +0 -6
  112. data/spec/assets/stemcell_invalid_mf.tgz +0 -0
  113. data/spec/assets/stemcell_no_image.tgz +0 -0
  114. data/spec/assets/valid_release.tgz +0 -0
  115. data/spec/assets/valid_stemcell.tgz +0 -0
  116. data/spec/spec_helper.rb +0 -28
  117. data/spec/unit/base_command_spec.rb +0 -87
  118. data/spec/unit/biff_spec.rb +0 -172
  119. data/spec/unit/blob_manager_spec.rb +0 -288
  120. data/spec/unit/cache_spec.rb +0 -36
  121. data/spec/unit/cli_commands_spec.rb +0 -356
  122. data/spec/unit/config_spec.rb +0 -125
  123. data/spec/unit/core_ext_spec.rb +0 -81
  124. data/spec/unit/dependency_helper_spec.rb +0 -52
  125. data/spec/unit/deployment_manifest_compiler_spec.rb +0 -63
  126. data/spec/unit/deployment_manifest_spec.rb +0 -153
  127. data/spec/unit/director_spec.rb +0 -471
  128. data/spec/unit/director_task_spec.rb +0 -48
  129. data/spec/unit/event_log_renderer_spec.rb +0 -171
  130. data/spec/unit/hash_changeset_spec.rb +0 -73
  131. data/spec/unit/job_builder_spec.rb +0 -455
  132. data/spec/unit/job_property_collection_spec.rb +0 -111
  133. data/spec/unit/job_property_validator_spec.rb +0 -7
  134. data/spec/unit/job_rename_spec.rb +0 -200
  135. data/spec/unit/package_builder_spec.rb +0 -593
  136. data/spec/unit/release_builder_spec.rb +0 -120
  137. data/spec/unit/release_spec.rb +0 -173
  138. data/spec/unit/release_tarball_spec.rb +0 -29
  139. data/spec/unit/runner_spec.rb +0 -7
  140. data/spec/unit/ssh_spec.rb +0 -84
  141. data/spec/unit/stemcell_spec.rb +0 -17
  142. data/spec/unit/task_tracker_spec.rb +0 -131
  143. data/spec/unit/version_calc_spec.rb +0 -27
  144. data/spec/unit/versions_index_spec.rb +0 -144
@@ -1,125 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
-
5
- describe Bosh::Cli::Config do
6
- before :each do
7
- @config = File.join(Dir.mktmpdir, "bosh_config")
8
- @cache_dir = Dir.mktmpdir
9
- end
10
-
11
- def add_config(object)
12
- File.open(@config, "w") do |f|
13
- f.write(YAML.dump(object))
14
- end
15
- end
16
-
17
- def create_config
18
- Bosh::Cli::Config.new(@config)
19
- end
20
-
21
- it "should convert old deployment configs to the new config " +
22
- "when set_deployment is called" do
23
- add_config("target" => "localhost:8080", "deployment" => "test")
24
-
25
- cfg = create_config
26
- yaml_file = load_yaml_file(@config, nil)
27
- yaml_file["deployment"].should == "test"
28
- cfg.set_deployment("test2")
29
- cfg.save
30
- yaml_file = load_yaml_file(@config, nil)
31
- yaml_file["deployment"].has_key?("localhost:8080").should be_true
32
- yaml_file["deployment"]["localhost:8080"].should == "test2"
33
- end
34
-
35
- it "should convert old deployment configs to the new config " +
36
- "when deployment is called" do
37
- add_config("target" => "localhost:8080", "deployment" => "test")
38
-
39
- cfg = create_config
40
- yaml_file = load_yaml_file(@config, nil)
41
- yaml_file["deployment"].should == "test"
42
- cfg.deployment.should == "test"
43
- yaml_file = load_yaml_file(@config, nil)
44
- yaml_file["deployment"].has_key?("localhost:8080").should be_true
45
- yaml_file["deployment"]["localhost:8080"].should == "test"
46
- end
47
-
48
- it "should save a deployment for each target" do
49
- add_config({})
50
- cfg = create_config
51
- cfg.target = "localhost:1"
52
- cfg.set_deployment("/path/to/deploy/1")
53
- cfg.save
54
- cfg.target = "localhost:2"
55
- cfg.set_deployment("/path/to/deploy/2")
56
- cfg.save
57
-
58
- # Test that the file is written correctly.
59
- yaml_file = load_yaml_file(@config, nil)
60
- yaml_file["deployment"].has_key?("localhost:1").should be_true
61
- yaml_file["deployment"].has_key?("localhost:2").should be_true
62
- yaml_file["deployment"]["localhost:1"].should == "/path/to/deploy/1"
63
- yaml_file["deployment"]["localhost:2"].should == "/path/to/deploy/2"
64
-
65
- # Test that switching targets gives you the new deployment.
66
- cfg.deployment.should == "/path/to/deploy/2"
67
- cfg.target = "localhost:1"
68
- cfg.deployment.should == "/path/to/deploy/1"
69
- end
70
-
71
- it "returns nil when the deployments key exists but has no value" do
72
- add_config("target" => "localhost:8080", "deployment" => nil)
73
-
74
- cfg = create_config
75
- yaml_file = load_yaml_file(@config, nil)
76
- yaml_file["deployment"].should == nil
77
- cfg.deployment.should == nil
78
- end
79
-
80
- it "should throw MissingTarget when getting deployment without target set" do
81
- add_config({})
82
- cfg = create_config
83
- expect { cfg.set_deployment("/path/to/deploy/1") }.
84
- to raise_error(Bosh::Cli::MissingTarget)
85
- end
86
-
87
- it "whines on missing config file" do
88
- lambda {
89
- File.should_receive(:open).with(@config, "w").and_raise(Errno::EACCES)
90
- create_config
91
- }.should raise_error(Bosh::Cli::ConfigError)
92
- end
93
-
94
-
95
- it "effectively ignores config file if it is malformed" do
96
- add_config([1, 2, 3])
97
- cfg = create_config
98
-
99
- cfg.target.should == nil
100
- end
101
-
102
- it "fetches auth information from the config file" do
103
- config = {
104
- "target" => "localhost:8080",
105
- "deployment" => "test",
106
- "auth" => {
107
- "localhost:8080" => { "username" => "a", "password" => "b" },
108
- "localhost:8081" => { "username" => "c", "password" => "d" }
109
- }
110
- }
111
-
112
- add_config(config)
113
- cfg = create_config
114
-
115
- cfg.username("localhost:8080").should == "a"
116
- cfg.password("localhost:8080").should == "b"
117
-
118
- cfg.username("localhost:8081").should == "c"
119
- cfg.password("localhost:8081").should == "d"
120
-
121
- cfg.username("localhost:8083").should be_nil
122
- cfg.password("localhost:8083").should be_nil
123
- end
124
-
125
- end
@@ -1,81 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
-
5
- describe String do
6
-
7
- it "can tell valid bosh identifiers from invalid" do
8
- %w(ruby ruby-1.8.7 mysql-2.3.5-alpha Apache_2.3).each do |id|
9
- id.bosh_valid_id?.should be_true
10
- end
11
-
12
- ["ruby 1.8", "ruby-1.8@b29", "#!@", "db/2", "ruby(1.8)"].each do |id|
13
- id.bosh_valid_id?.should be_false
14
- end
15
- end
16
-
17
- it "can tell blank string from non-blank" do
18
- [" ", "\t\t", "\n", ""].each do |string|
19
- string.should be_blank
20
- end
21
-
22
- ["a", " a", "a ", " a ", "___", "z\tb"].each do |string|
23
- string.should_not be_blank
24
- end
25
- end
26
-
27
- it "has colorization helpers (but only if tty)" do
28
- Bosh::Cli::Config.colorize = false
29
- "string".red.should == "string"
30
- "string".green.should == "string"
31
- "string".colorize("a").should == "string"
32
- "string".colorize(:green).should == "string"
33
-
34
- Bosh::Cli::Config.colorize = true
35
- Bosh::Cli::Config.output.stub(:tty?).and_return(true)
36
- "string".red.should == "\e[0m\e[31mstring\e[0m"
37
- "string".green.should == "\e[0m\e[32mstring\e[0m"
38
- "string".colorize("a").should == "string"
39
- "string".colorize(:green).should == "\e[0m\e[32mstring\e[0m"
40
-
41
- Bosh::Cli::Config.output.stub(:tty?).and_return(false)
42
- "string".green.should == "string"
43
- end
44
- end
45
-
46
- describe Object do
47
-
48
- it "has output helpers" do
49
- s = StringIO.new
50
- Bosh::Cli::Config.output = s
51
- say("yea")
52
- say("yea")
53
- s.rewind
54
- s.read.should == "yea\nyea\n"
55
-
56
- s.rewind
57
- header("test")
58
- s.rewind
59
- s.read.should == "\ntest\n----\n"
60
-
61
- s.rewind
62
- header("test", "a")
63
- s.rewind
64
- s.read.should == "\ntest\naaaa\n"
65
- end
66
-
67
- it "raises a special exception to signal a premature exit" do
68
- lambda {
69
- err("Done")
70
- }.should raise_error(Bosh::Cli::CliError, "Done")
71
- end
72
-
73
- it "can tell if object is blank" do
74
- o = Object.new
75
- o.stub!(:to_s).and_return(" ")
76
- o.should be_blank
77
- o.stub!(:to_s).and_return("Object 1")
78
- o.should_not be_blank
79
- end
80
-
81
- end
@@ -1,52 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
-
5
- describe Bosh::Cli::DependencyHelper do
6
-
7
- def sorter
8
- object = Object.new
9
- class << object
10
- include Bosh::Cli::DependencyHelper
11
- end
12
- object
13
- end
14
-
15
- def tsort_packages(*args)
16
- sorter.tsort_packages(*args)
17
- end
18
-
19
- def partial_order_sort(*args)
20
- sorter.partial_order_sort(*args)
21
- end
22
-
23
- it "resolves sorts simple dependencies" do
24
- tsort_packages("A" => ["B"], "B" => ["C"], "C" => []).
25
- should == ["C", "B", "A"]
26
- end
27
-
28
- it "whines on missing dependencies" do
29
- lambda {
30
- tsort_packages("A" => ["B"], "C" => ["D"])
31
- }.should raise_error Bosh::Cli::MissingDependency,
32
- "Package 'A' depends on missing package 'B'"
33
- end
34
-
35
- it "whines on circular dependencies" do
36
- lambda {
37
- tsort_packages("foo" => ["bar"], "bar" => ["baz"], "baz" => ["foo"])
38
- }.should raise_error(Bosh::Cli::CircularDependency,
39
- "Cannot resolve dependencies for 'bar': " +
40
- "circular dependency with 'foo'")
41
- end
42
-
43
- it "can resolve nested dependencies" do
44
- sorted = tsort_packages("A" => ["B", "C"], "B" => ["C", "D"],
45
- "C" => ["D"], "D" => [], "E" => [])
46
- sorted.index("B").should <= sorted.index("A")
47
- sorted.index("C").should <= sorted.index("A")
48
- sorted.index("D").should <= sorted.index("B")
49
- sorted.index("D").should <= sorted.index("C")
50
- end
51
-
52
- end
@@ -1,63 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
-
5
- describe Bosh::Cli::DeploymentManifestCompiler do
6
-
7
- def make_compiler(manifest, properties = {})
8
- compiler = Bosh::Cli::DeploymentManifestCompiler.new(manifest)
9
- compiler.properties = properties
10
- compiler
11
- end
12
-
13
- it "substitutes properties in a raw manifest" do
14
- raw_manifest = <<-MANIFEST.gsub(/^\s*/, "")
15
- ---
16
- name: mycloud
17
- properties:
18
- dea:
19
- max_memory: <%= property("dea.max_memory") %>
20
- MANIFEST
21
-
22
- compiler = make_compiler(raw_manifest, { "dea.max_memory" => 8192 })
23
-
24
- compiler.result.should == <<-MANIFEST.gsub(/^\s*/, "")
25
- ---
26
- name: mycloud
27
- properties:
28
- dea:
29
- max_memory: 8192
30
- MANIFEST
31
- end
32
-
33
- it "whines on missing deployment properties" do
34
- raw_manifest = <<-MANIFEST.gsub(/^\s*/, "")
35
- ---
36
- name: mycloud
37
- properties:
38
- dea:
39
- max_memory: <%= property("missing.property") %>
40
- MANIFEST
41
-
42
- compiler = make_compiler(raw_manifest, { "dea.max_memory" => 8192 })
43
- error_msg = "Cannot resolve deployment property `missing.property'"
44
-
45
- lambda {
46
- compiler.result
47
- }.should raise_error(Bosh::Cli::UndefinedProperty, error_msg)
48
- end
49
-
50
- it "whines if manifest has syntax error (from ERB's point of view)" do
51
- raw_manifest = <<-MANIFEST.gsub(/^\s*/, "")
52
- properties: <%=
53
- dea:
54
- max_memory: <%= property("missing.property") %>
55
- MANIFEST
56
-
57
- compiler = make_compiler(raw_manifest, { "dea.max_memory" => 8192 })
58
-
59
- lambda {
60
- compiler.result
61
- }.should raise_error(Bosh::Cli::MalformedManifest)
62
- end
63
- end
@@ -1,153 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
-
5
- describe Bosh::Cli::DeploymentHelper do
6
-
7
- def make_cmd(options = {})
8
- cmd = Bosh::Cli::Command::Base.new(options)
9
- cmd.extend(Bosh::Cli::DeploymentHelper)
10
- cmd
11
- end
12
-
13
- it "checks that actual director UUID matches the one in manifest" do
14
- cmd = make_cmd
15
- manifest = {
16
- "name" => "mycloud",
17
- "director_uuid" => "deadbeef"
18
- }
19
-
20
- manifest_file = Tempfile.new("manifest")
21
- YAML.dump(manifest, manifest_file)
22
- manifest_file.close
23
- director = mock(Bosh::Cli::Director)
24
-
25
- cmd.stub!(:deployment).and_return(manifest_file.path)
26
- cmd.stub!(:director).and_return(director)
27
-
28
- director.should_receive(:uuid).and_return("deadcafe")
29
-
30
- expect {
31
- cmd.prepare_deployment_manifest
32
- }.to raise_error(/Target director UUID doesn't match/i)
33
- end
34
-
35
- it "resolves 'latest' release alias for multiple releases" do
36
- cmd = make_cmd
37
- manifest = {
38
- "name" => "mycloud",
39
- "director_uuid" => "deadbeef",
40
- "releases" => [
41
- {"name" => "foo", "version" => "latest"},
42
- {"name" => "bar", "version" => "latest"},
43
- {"name" => "baz", "version" => 3},
44
- ]
45
- }
46
-
47
- manifest_file = Tempfile.new("manifest")
48
- YAML.dump(manifest, manifest_file)
49
- manifest_file.close
50
- director = mock(Bosh::Cli::Director, :uuid => "deadbeef")
51
-
52
- cmd.stub!(:deployment).and_return(manifest_file.path)
53
- cmd.stub!(:director).and_return(director)
54
-
55
- releases = [
56
- {"name" => "foo", "versions" => %w(1 3.5.7-dev 2 3.5.2-dev)},
57
- {"name" => "bar", "versions" => %w(4 2 3 1 1.1-dev 3.99-dev)},
58
- {"name" => "baz", "versions" => %w(1 2 3 4 5 6 7)}
59
- ]
60
-
61
- director.should_receive(:list_releases).and_return(releases)
62
-
63
- manifest = cmd.prepare_deployment_manifest
64
- manifest["releases"][0]["version"].should == "3.5.7-dev"
65
- manifest["releases"][1]["version"].should == 4 # cast to Integer!
66
- manifest["releases"][2]["version"].should == 3
67
- end
68
-
69
- it "resolves 'latest' release alias for a single release" do
70
- cmd = make_cmd
71
- manifest = {
72
- "name" => "mycloud",
73
- "director_uuid" => "deadbeef",
74
- "release" => {"name" => "foo", "version" => "latest"}
75
- }
76
-
77
- manifest_file = Tempfile.new("manifest")
78
- YAML.dump(manifest, manifest_file)
79
- manifest_file.close
80
- director = mock(Bosh::Cli::Director, :uuid => "deadbeef")
81
-
82
- cmd.stub!(:deployment).and_return(manifest_file.path)
83
- cmd.stub!(:director).and_return(director)
84
-
85
- releases = [
86
- {"name" => "foo", "versions" => %w(1 3.5.7-dev 2 3.5.2-dev)},
87
- ]
88
-
89
- director.should_receive(:list_releases).and_return(releases)
90
-
91
- manifest = cmd.prepare_deployment_manifest
92
- manifest["release"]["version"].should == "3.5.7-dev"
93
- end
94
-
95
- it "treats having both 'releases' and 'release' as error" do
96
- cmd = make_cmd
97
- manifest = {
98
- "name" => "mycloud",
99
- "director_uuid" => "deadbeef",
100
- "release" => {"name" => "foo", "version" => "latest"},
101
- "releases" => []
102
- }
103
-
104
- manifest_file = Tempfile.new("manifest")
105
- YAML.dump(manifest, manifest_file)
106
- manifest_file.close
107
- director = mock(Bosh::Cli::Director, :uuid => "deadbeef")
108
-
109
- cmd.stub!(:deployment).and_return(manifest_file.path)
110
- cmd.stub!(:director).and_return(director)
111
-
112
- expect {
113
- cmd.prepare_deployment_manifest
114
- }.to raise_error(/manifest has both `release' and `releases'/i)
115
- end
116
-
117
- it "resolves 'latest' release alias for multiple stemcells" do
118
- cmd = make_cmd
119
- manifest = {
120
- "name" => "mycloud",
121
- "director_uuid" => "deadbeef",
122
- "release" => {"name" => "appcloud", "version" => 42},
123
- "resource_pools" => [
124
- {"stemcell" => {"name" => "foo", "version" => "latest"}},
125
- {"stemcell" => {"name" => "foo", "version" => 22}},
126
- {"stemcell" => {"name" => "bar", "version" => "latest"}},
127
- ]
128
- }
129
-
130
- manifest_file = Tempfile.new("manifest")
131
- YAML.dump(manifest, manifest_file)
132
- manifest_file.close
133
- director = mock(Bosh::Cli::Director, :uuid => "deadbeef")
134
-
135
- cmd.stub!(:deployment).and_return(manifest_file.path)
136
- cmd.stub!(:director).and_return(director)
137
-
138
- stemcells = [
139
- {"name" => "foo", "version" => "22.6.4"},
140
- {"name" => "foo", "version" => "22"},
141
- {"name" => "bar", "version" => "4.0.8"},
142
- {"name" => "bar", "version" => "4.1"}
143
- ]
144
-
145
- director.should_receive(:list_stemcells).and_return(stemcells)
146
-
147
- manifest = cmd.prepare_deployment_manifest
148
- manifest["resource_pools"][0]["stemcell"]["version"].should == "22.6.4"
149
- manifest["resource_pools"][1]["stemcell"]["version"].should == 22
150
- manifest["resource_pools"][2]["stemcell"]["version"].should == 4.1
151
- end
152
-
153
- end