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