bosh-workspace 0.7.0 → 0.8.0

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 (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