bosh-workspace 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +5 -13
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +2 -2
  6. data/README.md +78 -39
  7. data/Rakefile +4 -0
  8. data/bosh-workspace.gemspec +4 -1
  9. data/lib/bosh/cli/commands/prepare.rb +74 -0
  10. data/lib/bosh/cli/commands/{01_make_manifest.rb → project_deployment.rb} +4 -26
  11. data/lib/bosh/workspace.rb +7 -3
  12. data/lib/bosh/workspace/helpers/dns_helper.rb +72 -0
  13. data/lib/bosh/workspace/helpers/project_deployment_helper.rb +8 -3
  14. data/lib/bosh/workspace/helpers/release_helper.rb +33 -0
  15. data/lib/bosh/workspace/helpers/spiff_helper.rb +1 -1
  16. data/lib/bosh/workspace/helpers/stemcell_helper.rb +45 -0
  17. data/lib/bosh/workspace/manifest_builder.rb +10 -25
  18. data/lib/bosh/workspace/project_deployment.rb +77 -0
  19. data/lib/bosh/workspace/release.rb +41 -33
  20. data/lib/bosh/workspace/stemcell.rb +23 -0
  21. data/lib/bosh/workspace/stub_file.rb +44 -0
  22. data/lib/bosh/workspace/version.rb +1 -1
  23. data/spec/assets/dns/job-properties.yml +22 -0
  24. data/spec/assets/dns/jobs.yml +18 -0
  25. data/spec/assets/dns/networks-manual.yml +19 -0
  26. data/spec/assets/dns/networks-no-manual.yml +18 -0
  27. data/spec/assets/dns/properties.yml +29 -0
  28. data/spec/assets/foo-boshrelease-repo.zip +0 -0
  29. data/spec/commands/prepare_spec.rb +99 -0
  30. data/spec/commands/{command_make_manifest_spec.rb → project_deployment_spec.rb} +4 -23
  31. data/spec/helpers/dns_helper_spec.rb +59 -0
  32. data/spec/helpers/project_deployment_helper_spec.rb +24 -23
  33. data/spec/helpers/release_helper_spec.rb +76 -0
  34. data/spec/helpers/spiff_helper_spec.rb +2 -2
  35. data/spec/helpers/stemcell_helper_spec.rb +89 -0
  36. data/spec/manifest_builder_spec.rb +24 -45
  37. data/spec/project_deployment_spec.rb +157 -0
  38. data/spec/release_spec.rb +39 -18
  39. data/spec/spec_helper.rb +9 -3
  40. data/spec/stemcell_spec.rb +28 -0
  41. data/spec/stub_file_spec.rb +74 -0
  42. metadata +90 -22
  43. data/lib/bosh/workspace/deployment_manifest.rb +0 -67
  44. data/lib/bosh/workspace/release_manager.rb +0 -14
  45. data/spec/deployment_manifest_spec.rb +0 -93
  46. data/spec/release_manager_spec.rb +0 -17
@@ -1,7 +1,7 @@
1
- describe Bosh::Manifests::SpiffHelper do
1
+ describe Bosh::Workspace::SpiffHelper do
2
2
  describe ".spiff" do
3
3
  class SpiffHelperTester
4
- include Bosh::Manifests::SpiffHelper
4
+ include Bosh::Workspace::SpiffHelper
5
5
  end
6
6
  subject { SpiffHelperTester.new }
7
7
  let(:path) { asset_dir("bin") }
@@ -0,0 +1,89 @@
1
+ describe Bosh::Workspace::StemcellHelper do
2
+ class StemcellHelperTester
3
+ include Bosh::Workspace::StemcellHelper
4
+
5
+ attr_reader :director, :work_dir
6
+
7
+ def initialize(director, work_dir)
8
+ @director = director
9
+ @work_dir = work_dir
10
+ end
11
+ end
12
+
13
+ subject { stemcell_helper }
14
+ let(:stemcell_helper) { StemcellHelperTester.new(director, work_dir) }
15
+ let(:director) { instance_double('Bosh::Cli::Client::Director') }
16
+ let(:work_dir) { asset_dir("manifests-repo") }
17
+
18
+ context "with stemcell command" do
19
+ let(:stemcell_cmd) { instance_double("Bosh::Cli::Command::Stemcell") }
20
+ before { Bosh::Cli::Command::Stemcell.stub(:new).and_return(stemcell_cmd) }
21
+
22
+ describe "#stemcell_download" do
23
+ let(:name) { "foo" }
24
+ subject { stemcell_helper.stemcell_download(name) }
25
+
26
+ it "downloads stemcell" do
27
+ Dir.should_receive(:chdir).and_yield
28
+ stemcell_cmd.should_receive(:download_public).with(name)
29
+ subject
30
+ end
31
+ end
32
+
33
+ describe "#stemcell_upload" do
34
+ let(:file) { "foo.tgz" }
35
+ subject { stemcell_helper.stemcell_upload(file) }
36
+
37
+ it "uploads stemcell" do
38
+ stemcell_cmd.should_receive(:upload).with(file)
39
+ subject
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#stemcell_uploaded?" do
45
+ let(:stemcells) { [{ "name" => "foo", "version" => "1" }] }
46
+ subject { stemcell_helper.stemcell_uploaded?(name, 1) }
47
+ before { director.should_receive(:list_stemcells).and_return(stemcells) }
48
+
49
+ context "stemcell exists" do
50
+ let(:name) { "foo" }
51
+ it { should be_true }
52
+ end
53
+
54
+ context "stemcell not found" do
55
+ let(:name) { "bar" }
56
+ it { should be_false }
57
+ end
58
+ end
59
+
60
+ describe "#stemcell_dir" do
61
+ let(:stemcells_dir) { File.join(work_dir, ".stemcells") }
62
+ subject { stemcell_helper.stemcells_dir }
63
+
64
+ before { FileUtils.should_receive(:mkdir_p).once.with(stemcells_dir).and_return([stemcells_dir]) }
65
+
66
+ it { should eq stemcells_dir }
67
+
68
+ it "memoizes" do
69
+ subject
70
+ expect(subject).to eq stemcells_dir
71
+ end
72
+ end
73
+
74
+ describe "#project_deployment_stemcells" do
75
+ subject { stemcell_helper.project_deployment_stemcells }
76
+ let(:stemcell) { instance_double("Bosh::Workspace::Stemcell") }
77
+ let(:stemcell_data) { { name: "foo" } }
78
+ let(:stemcells) { [stemcell_data, stemcell_data] }
79
+
80
+ before { stemcell_helper.stub_chain("project_deployment.stemcells").and_return(stemcells) }
81
+
82
+ it "inits stemcells once" do
83
+ Bosh::Workspace::Stemcell.should_receive(:new).twice
84
+ .with(stemcell_data, /\/.stemcells/).and_return(stemcell)
85
+ subject
86
+ expect(subject).to eq [stemcell, stemcell]
87
+ end
88
+ end
89
+ end
@@ -1,72 +1,45 @@
1
- describe Bosh::Manifests::ManifestBuilder do
2
- let(:manifest) { instance_double("Bosh::Manifests::Manifest") }
1
+ describe Bosh::Workspace::ManifestBuilder do
2
+ let(:project_deployment) { instance_double("Bosh::Workspace::Project_Deployment",
3
+ name: "bar",
4
+ templates: ["foo.yml"],
5
+ merged_file: ".deployments/foo.yml")
6
+ }
3
7
  let(:work_dir) { asset_dir("manifests-repo") }
4
- let(:target_name) { "bar" }
5
- let(:target_file) {
6
- File.join(work_dir, ".manifests", "#{target_name}.yml") }
7
8
 
8
9
  describe ".build" do
9
- subject { Bosh::Manifests::ManifestBuilder.build manifest, work_dir }
10
+ subject { Bosh::Workspace::ManifestBuilder.build project_deployment, work_dir }
10
11
  let(:manifest_builder) {
11
- instance_double("Bosh::Manifests::ManifestBuilder") }
12
+ instance_double("Bosh::Workspace::ManifestBuilder") }
12
13
 
13
14
  it "creates builder and merges templates" do
14
- Bosh::Manifests::ManifestBuilder.should_receive(:new)
15
- .with(manifest, work_dir).and_return(manifest_builder)
15
+ Bosh::Workspace::ManifestBuilder.should_receive(:new)
16
+ .with(project_deployment, work_dir).and_return(manifest_builder)
16
17
  manifest_builder.should_receive(:merge_templates)
17
18
  subject
18
19
  end
19
20
  end
20
21
 
21
22
  describe "#merge_templates" do
22
- subject { Bosh::Manifests::ManifestBuilder.new manifest, work_dir }
23
- let(:templates) { ["foo.yml"] }
24
- let(:template_path) { File.join(work_dir, "templates/foo.yml") }
25
- let(:template_exists) { true }
23
+ subject { Bosh::Workspace::ManifestBuilder.new project_deployment, work_dir }
26
24
 
27
25
  before do
28
- manifest.should_receive(:templates).and_return(templates)
29
- File.should_receive(:exists?).with(template_path)
30
- .and_return(template_exists)
26
+ File.stub(:exists?).with(/templates\//).and_return(template_exists)
31
27
  end
32
28
 
33
29
  context "missing template" do
34
30
  let(:template_exists) { false }
35
31
  it "raises error" do
36
- expect{ subject.merge_templates }.to raise_error /does not exist/
32
+ expect{ subject.merge_templates }.to raise_error(/does not exist/)
37
33
  end
38
34
  end
39
35
 
40
36
  context "template exists" do
37
+ let(:template_exists) { true }
41
38
  let(:dir_exists) { true }
42
- let(:target_dir) { File.join(work_dir, ".manifests" ) }
43
- let(:uuid) { "foo-bar-uuid" }
44
- let(:meta_file_path) do
45
- File.join(work_dir, ".stubs", "#{target_name}.yml")
46
- end
47
- let(:meta_file) { instance_double("File") }
48
- let(:meta) { { "foo" => "bar" } }
49
- let(:release) { { "name" => "foo", "version" => "latest" } }
50
- let(:releases) { [release] }
51
- let(:raw_releases) { [release.merge("git" => "release_repo.git")] }
52
- let(:meta_file_content) do
53
- {
54
- "director_uuid" => uuid,
55
- "releases" => releases,
56
- "meta" => meta
57
- }
58
- end
59
39
 
60
40
  before do
61
- manifest.should_receive(:name).and_return(target_name)
62
- manifest.should_receive(:meta).and_return(meta)
63
- manifest.should_receive(:director_uuid).and_return(uuid)
64
- manifest.should_receive(:releases).and_return(raw_releases)
65
- manifest.should_receive(:merged_file).and_return(target_file)
66
- File.should_receive(:exists?).and_return(dir_exists)
67
- File.should_receive(:open).with(meta_file_path, "w")
68
- .and_yield(meta_file)
69
- meta_file.should_receive(:write).with(meta_file_content.to_yaml)
41
+ File.stub(:exists?).with(/\.stubs/).and_return(dir_exists)
42
+ Bosh::Workspace::StubFile.should_receive(:create).with(/\.stubs\/.+yml/, project_deployment)
70
43
  end
71
44
 
72
45
  context "no hidden dirs" do
@@ -79,8 +52,14 @@ describe Bosh::Manifests::ManifestBuilder do
79
52
  end
80
53
 
81
54
  it "generates manifest with spiff" do
82
- subject.should_receive(:spiff_merge)
83
- .with([template_path, meta_file_path], target_file)
55
+ subject.should_receive(:spiff_merge) do |args|
56
+ if args.is_a?(Array)
57
+ expect(args.first).to match(/\/templates\/.+yml/)
58
+ expect(args.last).to match(/\.stubs\/.+yml/)
59
+ else
60
+ expect(args).to match(/\.deployments\/.+yml/)
61
+ end
62
+ end
84
63
  subject.merge_templates
85
64
  end
86
65
  end
@@ -0,0 +1,157 @@
1
+ describe Bosh::Workspace::ProjectDeployment do
2
+ let(:project_deployment) { Bosh::Workspace::ProjectDeployment.new manifest_file }
3
+ let(:manifest_file) { get_tmp_file_path(manifest.to_yaml, file_name) }
4
+ let(:file_name) { "foo.yml" }
5
+ let(:name) { "foo" }
6
+ let(:uuid) { "e55134c3-0a63-47be-8409-c9e53e965d5c" }
7
+ let(:domain_name) { "bosh" }
8
+ let(:templates) { ["path_to_bar", "path_to_baz"] }
9
+ let(:releases) { [
10
+ { "name" => "foo", "version" => release_version, "git" => "example.com/foo.git" }
11
+ ] }
12
+ let(:release_version) { 1 }
13
+ let(:stemcells) { [
14
+ { "name" => "bar", "version" => stemcell_version }
15
+ ] }
16
+ let(:stemcell_version) { 1 }
17
+ let(:meta) { { "foo" => "bar" } }
18
+ let(:manifest) { {
19
+ "name" => name,
20
+ "director_uuid" => uuid,
21
+ "domain_name" => domain_name,
22
+ "templates" => templates,
23
+ "releases" => releases,
24
+ "stemcells" => stemcells,
25
+ "meta" => meta,
26
+ } }
27
+
28
+ subject { project_deployment }
29
+
30
+ describe "#perform_validation" do
31
+ subject { project_deployment.errors.first }
32
+ let(:invalid_manifest) do
33
+ if defined?(missing)
34
+ manifest.delete_if { |key| Array(missing).include?(key) }
35
+ else
36
+ manifest
37
+ end
38
+ end
39
+ let(:manifest_file) { get_tmp_file_path(invalid_manifest.to_yaml) }
40
+
41
+ before do
42
+ project_deployment.validate
43
+ expect(project_deployment).to_not be_valid
44
+ end
45
+
46
+ context "not a hash" do
47
+ let(:invalid_manifest) { "foo" }
48
+ it { should match(/Expected instance of Hash/) }
49
+ end
50
+
51
+ %w(name director_uuid releases templates meta stemcells).each do |field|
52
+ context "missing #{field}" do
53
+ let(:missing) { field }
54
+ it { should match(/#{field}.*missing/i) }
55
+ end
56
+ end
57
+
58
+ context "optional domain_name" do
59
+ let(:missing) { ["domain_name", "director_uuid"] }
60
+ it { should match(/director_uuid/) }
61
+ it { should_not match(/domain_name/) }
62
+ end
63
+
64
+ context "director_uuid" do
65
+ context "invalid" do
66
+ let(:uuid) { "invalid_uuid" }
67
+ it { should match(/director_uuid.*doesn't validate/) }
68
+ end
69
+
70
+ context "current" do
71
+ let(:uuid) { "current" }
72
+ let(:missing) { "name" }
73
+ it { should_not match(/director_uuid/) }
74
+ it { should match(/name/) }
75
+ end
76
+ end
77
+
78
+ context "releases" do
79
+ let(:invalid_manifest) do
80
+ manifest["releases"].map! { |r| r.delete_if { |key| Array(missing).include?(key) } }
81
+ manifest
82
+ end
83
+
84
+ %w(name version git).each do |field_name|
85
+ context "missing #{field_name}" do
86
+ let(:missing) { field_name }
87
+ it { should match(/#{field_name}.*missing/i) }
88
+ end
89
+ end
90
+
91
+ context "latest version" do
92
+ let(:missing) { "git" }
93
+ let(:release_version) { "latest" }
94
+ it { should match(/git.*missing/i) }
95
+ it { should_not match(/version/i) }
96
+ end
97
+
98
+ context "invalid version" do
99
+ let(:missing) { "git" }
100
+ let(:release_version) { "foo" }
101
+ it { should match(/git.*missing/i) }
102
+ it { should match(/version.*doesn't validate/i) }
103
+ end
104
+ end
105
+
106
+ context "stemcells" do
107
+ let(:invalid_manifest) do
108
+ manifest["stemcells"].map! { |r| r.delete_if { |key| Array(missing).include?(key) } }
109
+ manifest
110
+ end
111
+
112
+ %w(name version).each do |field_name|
113
+ context "missing #{field_name}" do
114
+ let(:missing) { field_name }
115
+ it { should match(/#{field_name}.*missing/i) }
116
+ end
117
+ end
118
+
119
+ context "latest version" do
120
+ let(:missing) { "name" }
121
+ let(:stemcell_version) { "latest" }
122
+ it { should match(/name.*missing/i) }
123
+ it { should_not match(/version/i) }
124
+ end
125
+
126
+ context "invalid version" do
127
+ let(:missing) { "name" }
128
+ let(:stemcell_version) { "foo" }
129
+ it { should match(/name.*missing/i) }
130
+ it { should match(/version.*doesn't validate/i) }
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "#director_uuid=" do
136
+ before { subject.director_uuid = "foo-bar" }
137
+ its(:director_uuid) { should eq "foo-bar" }
138
+ end
139
+
140
+ describe "attr readers" do
141
+ let(:director_uuid) { uuid }
142
+ %w(name director_uuid templates releases stemcells meta).each do |attr|
143
+ its(attr.to_sym) { should eq eval(attr) }
144
+ end
145
+ end
146
+
147
+ describe "#merged_file" do
148
+ it "creates parent directory" do
149
+ dir = File.dirname(subject.merged_file)
150
+ expect(File.directory?(dir)).to be_true
151
+ end
152
+
153
+ it "retruns merged file" do
154
+ expect(subject.merged_file).to match(/\.deployments\/#{file_name}/)
155
+ end
156
+ end
157
+ end
@@ -1,19 +1,20 @@
1
- describe Bosh::Manifests::Release do
1
+ describe Bosh::Workspace::Release do
2
2
  let(:name) { "foo"}
3
3
  let(:version) { 3 }
4
4
  let(:repo) { extracted_asset_dir("foo", "foo-boshrelease-repo.zip") }
5
5
  let(:release_data) { { "name" => name, "version" => version, "git" => repo } }
6
6
  let(:releases_dir) { File.join(asset_dir("manifests-repo"), ".releases") }
7
- let(:release) { Bosh::Manifests::Release.new release_data, releases_dir }
8
- subject { Dir[File.join(releases_dir, name, "releases", "foo*.yml")].to_s }
7
+ let(:release) { Bosh::Workspace::Release.new release_data, releases_dir }
8
+
9
+ describe "#update_repo" do
10
+ subject { Dir[File.join(releases_dir, name, "releases", "foo*.yml")].to_s }
9
11
 
10
- describe "#checkout_current_version" do
11
12
  context "latest version" do
12
13
  let(:version) { "latest" }
13
14
 
14
15
  it "checks out repo" do
15
- release.checkout_current_version
16
- expect(subject).to match /foo-11.yml/
16
+ release.update_repo
17
+ expect(subject).to match(/foo-11.yml/)
17
18
  end
18
19
  end
19
20
 
@@ -21,8 +22,17 @@ describe Bosh::Manifests::Release do
21
22
  let(:version) { "2" }
22
23
 
23
24
  it "checks out repo" do
24
- release.checkout_current_version
25
- expect(subject).to match /foo-2.yml/
25
+ release.update_repo
26
+ expect(subject).to match(/foo-2.yml/)
27
+ end
28
+ end
29
+
30
+ context "updated version " do
31
+ let(:version) { "11" }
32
+
33
+ it "checks out file with multiple commits" do
34
+ release.update_repo
35
+ expect(subject).to match(/foo-11.yml/)
26
36
  end
27
37
  end
28
38
 
@@ -30,21 +40,21 @@ describe Bosh::Manifests::Release do
30
40
  let(:version) { "12" }
31
41
 
32
42
  it "raises an error" do
33
- expect { release.checkout_current_version }.
34
- to raise_error /Could not find version/
43
+ expect { release.update_repo }.
44
+ to raise_error(/Could not find version/)
35
45
  end
36
46
  end
37
47
 
38
48
  context "already cloned repo" do
39
49
  before do
40
50
  data = { "name" => name, "version" => 1, "git" => repo }
41
- cloned_release = Bosh::Manifests::Release.new(data, releases_dir)
42
- cloned_release.checkout_current_version
51
+ cloned_release = Bosh::Workspace::Release.new(data, releases_dir)
52
+ cloned_release.update_repo
43
53
  end
44
54
 
45
55
  it "version 3" do
46
- release.checkout_current_version
47
- expect(subject).to match /foo-3.yml/
56
+ release.update_repo
57
+ expect(subject).to match(/foo-3.yml/)
48
58
  end
49
59
  end
50
60
 
@@ -53,17 +63,28 @@ describe Bosh::Manifests::Release do
53
63
 
54
64
  before do
55
65
  data = { "name" => "bar", "version" => 2, "git" => repo }
56
- other_release = Bosh::Manifests::Release.new(data, releases_dir)
57
- other_release.checkout_current_version
66
+ other_release = Bosh::Workspace::Release.new(data, releases_dir)
67
+ other_release.update_repo
58
68
  end
59
69
 
60
70
  it "version 3" do
61
- release.checkout_current_version
62
- expect(subject).to match /foo-3.yml/
71
+ release.update_repo
72
+ expect(subject).to match(/foo-3.yml/)
63
73
  end
64
74
  end
65
75
  end
66
76
 
77
+ describe "attributes" do
78
+ subject { release }
79
+ its(:name){ should eq name }
80
+ its(:git_uri){ should eq repo }
81
+ its(:repo_dir){ should match(/\/#{name}$/) }
82
+ its(:manifest_file){ should match(/\/#{name}-#{version}.yml$/) }
83
+ its(:manifest){ should match "releases/#{name}-#{version}.yml$" }
84
+ its(:name_version){ should eq "#{name}/#{version}" }
85
+ its(:version){ should eq version }
86
+ end
87
+
67
88
  after do
68
89
  FileUtils.rm_r releases_dir
69
90
  end