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
@@ -0,0 +1,19 @@
1
+ ---
2
+ networks:
3
+ - name: floating
4
+ type: vip
5
+ cloud_properties: {}
6
+ - name: default
7
+ type: manual
8
+ subnets:
9
+ - name: private
10
+ range: 10.0.0.0/24
11
+ gateway: 10.0.0.254
12
+ reserved:
13
+ - 10.0.0.1 - 10.0.0.10
14
+ static:
15
+ - 10.0.0.50 - 10.0.0.100
16
+ cloud_properties:
17
+ net_id: 1202c961-504d-4afb-b044-623787746307
18
+
19
+ jobs: []
@@ -0,0 +1,18 @@
1
+ ---
2
+ networks:
3
+ - name: floating
4
+ type: vip
5
+ cloud_properties: {}
6
+ - name: default
7
+ subnets:
8
+ - name: private
9
+ range: 10.0.0.0/24
10
+ gateway: 10.0.0.254
11
+ reserved:
12
+ - 10.0.0.1 - 10.0.0.10
13
+ static:
14
+ - 10.0.0.50 - 10.0.0.100
15
+ cloud_properties:
16
+ net_id: 1202c961-504d-4afb-b044-623787746307
17
+
18
+ jobs: []
@@ -0,0 +1,29 @@
1
+ name: foo
2
+
3
+ networks:
4
+ - name: default
5
+ type: manual
6
+
7
+ jobs:
8
+ - name: first_job_az1
9
+ networks:
10
+ - name: default
11
+ static_ips:
12
+ - 10.0.0.50
13
+
14
+ - name: second_job_az1
15
+ networks:
16
+ - name: default
17
+ static_ips:
18
+ - 10.0.0.51
19
+ - 10.0.0.52
20
+
21
+ properties:
22
+ job1:
23
+ foo: bar
24
+ address: 10.0.0.50
25
+ job2:
26
+ machines:
27
+ - 10.0.0.51
28
+ - 10.0.0.52
29
+
@@ -0,0 +1,99 @@
1
+ require "bosh/cli/commands/prepare"
2
+
3
+ describe Bosh::Cli::Command::Prepare do
4
+ describe "#prepare" do
5
+ let(:command) { Bosh::Cli::Command::Prepare.new }
6
+ let(:release) do
7
+ instance_double("Bosh::Workspace::Release",
8
+ name: "foo", version: "1", repo_dir: ".releases/foo",
9
+ name_version: "foo/1", manifest_file: "releases/foo-1.yml")
10
+ end
11
+ let(:stemcell) do
12
+ instance_double("Bosh::Workspace::Stemcell",
13
+ name: "bar", version: "2", name_version: "bar/2",
14
+ file: ".stemcesll/bar-2.tgz", file_name: "bar-2.tgz")
15
+ end
16
+
17
+ before do
18
+ command.stub(:require_project_deployment)
19
+ command.stub(:auth_required)
20
+ command.stub(:project_deployment_releases).and_return(releases)
21
+ command.stub(:project_deployment_stemcells).and_return(stemcells)
22
+ end
23
+
24
+ describe "prepare_release(s/_repos)" do
25
+ let(:releases) { [ release ] }
26
+ let(:stemcells) { [] }
27
+
28
+ before do
29
+ release.should_receive(:update_repo)
30
+ command.should_receive(:release_uploaded?)
31
+ .with(release.name, release.version).and_return(release_uploaded)
32
+ end
33
+
34
+ context "release uploaded" do
35
+ let(:release_uploaded) { true }
36
+
37
+ it "does not upload the release" do
38
+ command.should_not_receive(:release_upload)
39
+ command.prepare
40
+ end
41
+ end
42
+
43
+ context "release not uploaded" do
44
+ let(:release_uploaded) { false }
45
+
46
+ it "does not upload the release" do
47
+ command.should_receive(:release_upload).with(release.manifest_file)
48
+ command.prepare
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "prepare_stemcells" do
54
+ let(:releases) { [] }
55
+ let(:stemcells) { [ stemcell ] }
56
+
57
+ before do
58
+ command.should_receive(:stemcell_uploaded?)
59
+ .with(stemcell.name, stemcell.version).and_return(stemcell_uploaded)
60
+ end
61
+
62
+ context "stemcell uploaded" do
63
+ let(:stemcell_uploaded) { true }
64
+
65
+ it "does not upload the stemcell" do
66
+ command.should_not_receive(:stemcell_download)
67
+ command.should_not_receive(:stemcell_upload)
68
+ command.prepare
69
+ end
70
+ end
71
+
72
+ context "stemcell not uploaded" do
73
+ let(:stemcell_uploaded) { false }
74
+
75
+ before { stemcell.should_receive(:downloaded?).and_return(stemcell_downloaded) }
76
+
77
+ context "stemcell downloaded" do
78
+ let(:stemcell_downloaded) { true }
79
+
80
+ it "does not upload the stemcell" do
81
+ command.should_not_receive(:stemcell_download)
82
+ command.should_receive(:stemcell_upload).with(stemcell.file)
83
+ command.prepare
84
+ end
85
+ end
86
+
87
+ context "stemcell downloaded" do
88
+ let(:stemcell_downloaded) { false }
89
+
90
+ it "does not upload the stemcell" do
91
+ command.should_receive(:stemcell_download).with(stemcell.file_name)
92
+ command.should_receive(:stemcell_upload).with(stemcell.file)
93
+ command.prepare
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,9 +1,9 @@
1
- require "bosh/cli/commands/01_make_manifest"
1
+ require "bosh/cli/commands/project_deployment"
2
2
 
3
- describe Bosh::Cli::Command::Manifests do
4
- let(:command) { Bosh::Cli::Command::Manifests.new }
3
+ describe Bosh::Cli::Command::ProjectDeployment do
4
+ let(:command) { Bosh::Cli::Command::ProjectDeployment.new }
5
5
  let(:project_deployment) do
6
- instance_double("Bosh::Manifests::DeploymentManifest")
6
+ instance_double("Bosh::Workspace::DeploymentManifest")
7
7
  end
8
8
 
9
9
  let(:deployment_cmd) { instance_double("Bosh::Cli::Command::Deployment") }
@@ -56,25 +56,6 @@ describe Bosh::Cli::Command::Manifests do
56
56
  end
57
57
  end
58
58
 
59
- describe "#prepare" do
60
- subject { command.prepare }
61
- let(:releases) { ["foo", "bar"] }
62
- let(:release_manager) { instance_double("Bosh::Manifests::ReleaseManager") }
63
- let(:work_dir) { asset_dir("manifests-repo") }
64
-
65
- it "resolves deployment requirements" do
66
- command.should_receive(:require_project_deployment)
67
- command.should_receive(:auth_required)
68
- command.should_receive(:project_deployment).and_return(project_deployment)
69
- project_deployment.should_receive(:releases).and_return(releases)
70
- command.should_receive(:work_dir).and_return(work_dir)
71
- Bosh::Manifests::ReleaseManager.should_receive(:new)
72
- .with(releases, work_dir).and_return(release_manager)
73
- release_manager.should_receive(:update_release_repos)
74
- subject
75
- end
76
- end
77
-
78
59
  describe "deploy" do
79
60
  subject { command.deploy }
80
61
 
@@ -0,0 +1,59 @@
1
+ describe Bosh::Workspace::DnsHelper do
2
+ describe ".transform" do
3
+ subject do
4
+ Bosh::Workspace::DnsHelper.transform(generated_manifest, domain_name)
5
+ YAML.load(IO.read(generated_manifest))
6
+ end
7
+
8
+ let(:generated_manifest) { get_tmp_file_path(content) }
9
+ let(:domain_name) { "microbosh" }
10
+
11
+ context "networks" do
12
+ let(:content) { asset_file("dns/networks-manual.yml") }
13
+
14
+ it "replaces manual networks" do
15
+ expect(subject["networks"][1]["type"]).to eq "dynamic"
16
+ end
17
+ end
18
+
19
+ context "no manual networks" do
20
+ let(:content) { asset_file("dns/networks-no-manual.yml") }
21
+
22
+ it "raises an error" do
23
+ expect { subject }.to raise_error /Missing manual network/
24
+ end
25
+ end
26
+
27
+ context "jobs" do
28
+ let(:content) { asset_file("dns/jobs.yml") }
29
+
30
+ it "removes static_ips of jobs with manual networks" do
31
+ expect(subject["jobs"][0]["networks"][0]).to_not include "static_ips"
32
+ expect(subject["jobs"][1]["networks"][0]).to_not include "static_ips"
33
+ end
34
+ end
35
+
36
+ context "properties" do
37
+ let(:content) { asset_file("dns/properties.yml") }
38
+
39
+ it "replaces ips with domains while keeping properties structure" do
40
+ expect(subject["properties"]["job1"]["address"])
41
+ .to eq "0.first-job-az1.default.foo.microbosh"
42
+ expect(subject["properties"]["job1"]["foo"]).to eq "bar"
43
+ expect(subject["properties"]["job2"]["machines"])
44
+ .to eq ["0.second-job-az1.default.foo.microbosh",
45
+ "1.second-job-az1.default.foo.microbosh"]
46
+ end
47
+ end
48
+
49
+ context "job properties" do
50
+ let(:content) { asset_file("dns/job-properties.yml") }
51
+
52
+ it "replaces ips with domains while keeping properties structure" do
53
+ expect(subject["jobs"][1]["properties"]["job1"]["address"])
54
+ .to eq "0.first-job-az1.default.foo.microbosh"
55
+ expect(subject["jobs"][1]["properties"]["job1"]["foo"]).to eq "bar"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,6 +1,6 @@
1
- describe Bosh::Manifests::ProjectDeploymentHelper do
2
- class HelperTester
3
- include Bosh::Manifests::ProjectDeploymentHelper
1
+ describe Bosh::Workspace::ProjectDeploymentHelper do
2
+ class ProjectDeploymentHelperTester
3
+ include Bosh::Workspace::ProjectDeploymentHelper
4
4
 
5
5
  attr_reader :director, :deployment
6
6
 
@@ -12,14 +12,17 @@ describe Bosh::Manifests::ProjectDeploymentHelper do
12
12
  end
13
13
 
14
14
  subject { project_deployment_helper }
15
- let(:project_deployment_helper) { HelperTester.new(director, deployment) }
15
+ let(:project_deployment_helper) do
16
+ ProjectDeploymentHelperTester.new(director, deployment, project_deployment)
17
+ end
16
18
  let(:deployment) { nil }
17
19
  let(:director) { instance_double('Bosh::Cli::Client::Director') }
18
20
  let(:work_dir) { asset_dir("manifests-repo") }
19
- let(:project_deployment) { instance_double("DeploymentManifest") }
21
+ let(:project_deployment) { instance_double("ProjectDeployment") }
20
22
 
21
23
  describe "project_deployment?" do
22
24
  subject { project_deployment_helper.project_deployment? }
25
+ let(:project_deployment_helper) { ProjectDeploymentHelperTester.new(director, deployment) }
23
26
  let(:deployment) { File.join work_dir, deployment_path }
24
27
 
25
28
  context "deployment" do
@@ -40,11 +43,12 @@ describe Bosh::Manifests::ProjectDeploymentHelper do
40
43
  end
41
44
 
42
45
  describe "#project_deployment(=)" do
46
+ let(:project_deployment_helper) { ProjectDeploymentHelperTester.new(director, deployment) }
43
47
  let(:deployment) { File.join work_dir, deployment_path }
44
48
  let(:deployment_path) { "deployments/foo.yml" }
45
49
 
46
50
  before do
47
- Bosh::Manifests::DeploymentManifest.should_receive(:new)
51
+ Bosh::Workspace::ProjectDeployment.should_receive(:new)
48
52
  .with(deployment).and_return(project_deployment)
49
53
  end
50
54
 
@@ -76,6 +80,8 @@ describe Bosh::Manifests::ProjectDeploymentHelper do
76
80
  end
77
81
 
78
82
  describe "#require_project_deployment" do
83
+ let(:project_deployment_helper) { ProjectDeploymentHelperTester.new(director, deployment) }
84
+
79
85
  before do
80
86
  subject.should_receive(:project_deployment?)
81
87
  .and_return(:is_project_deployment)
@@ -93,16 +99,13 @@ describe Bosh::Manifests::ProjectDeploymentHelper do
93
99
  let(:deployment) { "foo" }
94
100
  let(:is_project_deployment) { false }
95
101
  it "raises and error" do
96
- expect { subject.require_project_deployment }.to raise_error /foo/
102
+ expect { subject.require_project_deployment }.to raise_error(/foo/)
97
103
  end
98
104
  end
99
105
  end
100
106
 
101
107
  describe "#create_placeholder_deployment" do
102
108
  subject { project_deployment_helper.create_placeholder_deployment }
103
- let(:project_deployment_helper) do
104
- HelperTester.new(director, deployment, project_deployment)
105
- end
106
109
  let(:deployment) { "deployments/bar.yml" }
107
110
  let(:file) { instance_double('File') }
108
111
  let(:merged_file) { ".deployments/bar.yml" }
@@ -121,38 +124,36 @@ describe Bosh::Manifests::ProjectDeploymentHelper do
121
124
  end
122
125
 
123
126
  describe "#validate_project_deployment" do
124
- let(:project_deployment_helper) do
125
- HelperTester.new(director, deployment, project_deployment)
126
- end
127
-
128
127
  it "raises an error" do
129
128
  project_deployment.should_receive(:valid?).and_return(false)
130
129
  project_deployment.should_receive(:errors).and_return(["foo"])
131
130
  project_deployment.should_receive(:file).and_return(["foo.yml"])
132
- expect { subject.validate_project_deployment }.to raise_error /foo/
131
+ expect { subject.validate_project_deployment }.to raise_error(/foo/)
133
132
  end
134
133
  end
135
134
 
136
135
  describe "#build_project_deployment" do
137
136
  subject { project_deployment_helper.build_project_deployment }
138
- let(:project_deployment_helper) do
139
- HelperTester.new(director, deployment, project_deployment)
140
- end
137
+ let(:domain_name) { "bosh" }
138
+ let(:merged_file) { "foo/bar" }
141
139
 
142
140
  it "builds project deployment manifest" do
143
141
  project_deployment_helper.should_receive(:resolve_director_uuid)
144
142
  project_deployment_helper.should_receive(:work_dir).and_return(work_dir)
145
- Bosh::Manifests::ManifestBuilder.should_receive(:build)
143
+ project_deployment.should_receive(:domain_name).and_return(domain_name)
144
+ project_deployment.should_receive(:merged_file).and_return(merged_file)
145
+
146
+ Bosh::Workspace::ManifestBuilder.should_receive(:build)
146
147
  .with(project_deployment, work_dir)
148
+ Bosh::Workspace::DnsHelper.should_receive(:transform)
149
+ .with(merged_file, domain_name)
150
+
147
151
  subject
148
152
  end
149
153
  end
150
154
 
151
155
  describe "#resolve_director_uuid" do
152
156
  subject { project_deployment_helper.resolve_director_uuid }
153
- let(:project_deployment_helper) do
154
- HelperTester.new(director, deployment, project_deployment)
155
- end
156
157
  let(:status) { { "uuid" => current_uuid, "cpi" => cpi } }
157
158
  let(:current_uuid) { "current-uuid" }
158
159
 
@@ -184,7 +185,7 @@ describe Bosh::Manifests::ProjectDeploymentHelper do
184
185
  let(:uuid) { "current" }
185
186
  let(:cpi) { "not-warden" }
186
187
  it "raises an error" do
187
- expect { subject }.to raise_error /may not be used in production/
188
+ expect { subject }.to raise_error(/may not be used in production/)
188
189
  end
189
190
  end
190
191
  end
@@ -0,0 +1,76 @@
1
+ describe Bosh::Workspace::ReleaseHelper do
2
+ class ReleaseHelperTester
3
+ include Bosh::Workspace::ReleaseHelper
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 { release_helper }
14
+ let(:release_helper) { ReleaseHelperTester.new(director, work_dir) }
15
+ let(:director) { instance_double('Bosh::Cli::Client::Director') }
16
+ let(:work_dir) { asset_dir("manifests-repo") }
17
+
18
+ describe "#release_upload" do
19
+ let(:release_cmd) { instance_double("Bosh::Cli::Command::Release") }
20
+ before { Bosh::Cli::Command::Release.stub(:new).and_return(release_cmd) }
21
+
22
+ let(:manifest_file) { "foo-1.yml." }
23
+ subject { release_helper.release_upload(manifest_file) }
24
+
25
+ it "uploads release" do
26
+ release_cmd.should_receive(:upload).with(manifest_file)
27
+ subject
28
+ end
29
+ end
30
+
31
+ describe "#release_uploaded?" do
32
+ let(:releases) { { "versions" => %w(1 2 3) } }
33
+ subject { release_helper.release_uploaded?("foo", version) }
34
+ before { director.should_receive(:get_release).with("foo").and_return(releases) }
35
+
36
+ context "release exists" do
37
+ let(:version) { 2 }
38
+ it { should be_true }
39
+ end
40
+
41
+ context "release not found" do
42
+ let(:version) { "8" }
43
+ it { should be_false }
44
+ end
45
+ end
46
+
47
+ describe "#release_dir" do
48
+ let(:releases_dir) { File.join(work_dir, ".releases") }
49
+ subject { release_helper.releases_dir }
50
+
51
+ before { FileUtils.should_receive(:mkdir_p).once.with(releases_dir).and_return([releases_dir]) }
52
+
53
+ it { should eq releases_dir }
54
+
55
+ it "memoizes" do
56
+ subject
57
+ expect(subject).to eq releases_dir
58
+ end
59
+ end
60
+
61
+ describe "#project_deployment_releases" do
62
+ subject { release_helper.project_deployment_releases }
63
+ let(:release) { instance_double("Bosh::Workspace::Release") }
64
+ let(:release_data) { { name: "foo" } }
65
+ let(:releases) { [release_data, release_data] }
66
+
67
+ before { release_helper.stub_chain("project_deployment.releases").and_return(releases) }
68
+
69
+ it "inits releases once" do
70
+ Bosh::Workspace::Release.should_receive(:new).twice
71
+ .with(release_data, /\/.releases/).and_return(release)
72
+ subject
73
+ expect(subject).to eq [release, release]
74
+ end
75
+ end
76
+ end