bosh-workspace 0.8.5 → 0.9.0.rc1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -2
- data/.ruby-gemset +1 -1
- data/.travis.yml +2 -0
- data/Guardfile +2 -2
- data/README.md +4 -4
- data/bosh-workspace.gemspec +2 -1
- data/lib/bosh/cli/commands/deployment_patch.rb +96 -0
- data/lib/bosh/cli/commands/prepare.rb +6 -4
- data/lib/bosh/workspace/credentials.rb +30 -0
- data/lib/bosh/workspace/deployment_patch.rb +90 -0
- data/lib/bosh/workspace/helpers/git_credentials_helper.rb +95 -0
- data/lib/bosh/workspace/helpers/spiff_helper.rb +1 -0
- data/lib/bosh/workspace/project_deployment.rb +2 -44
- data/lib/bosh/workspace/release.rb +20 -23
- data/lib/bosh/workspace/schemas/credentials.rb +27 -0
- data/lib/bosh/workspace/schemas/deployment_patch.rb +15 -0
- data/lib/bosh/workspace/schemas/project_deployment.rb +21 -0
- data/lib/bosh/workspace/schemas/releases.rb +16 -0
- data/lib/bosh/workspace/schemas/stemcells.rb +25 -0
- data/lib/bosh/workspace/shell.rb +67 -0
- data/lib/bosh/workspace/tasks/bosh_command_runner.rb +29 -0
- data/lib/bosh/workspace/tasks/deployment.rb +63 -0
- data/lib/bosh/workspace/tasks/workspace.rake +69 -0
- data/lib/bosh/workspace/tasks.rb +15 -0
- data/lib/bosh/workspace/version.rb +1 -1
- data/lib/bosh/workspace.rb +14 -0
- data/spec/assets/foo-boshrelease-repo-new-structure.zip +0 -0
- data/spec/assets/foo-boshrelease-repo-updated.zip +0 -0
- data/spec/assets/foo-boshrelease-repo.zip +0 -0
- data/spec/assets/foo-boshworkspace.zip +0 -0
- data/spec/commands/deployment_patch_spec.rb +152 -0
- data/spec/commands/prepare_spec.rb +5 -3
- data/spec/credentials_spec.rb +46 -0
- data/spec/deployment_patch_spec.rb +171 -0
- data/spec/helpers/git_credentials_helper_spec.rb +160 -0
- data/spec/helpers/spiff_helper_spec.rb +16 -3
- data/spec/project_deployment_spec.rb +52 -163
- data/spec/release_spec.rb +208 -80
- data/spec/schemas/credentials_spec.rb +28 -0
- data/spec/schemas/deployment_patch_spec.rb +30 -0
- data/spec/schemas/project_deployment_spec.rb +45 -0
- data/spec/schemas/releases_spec.rb +31 -0
- data/spec/schemas/stemcells_spec.rb +37 -0
- data/spec/shell_spec.rb +70 -0
- data/spec/spec_helper.rb +11 -5
- data/spec/support/shared_contexts/rake.rb +37 -0
- data/spec/tasks/bosh_command_runner_spec.rb +39 -0
- data/spec/tasks/deployment_spec.rb +80 -0
- data/spec/tasks/workspace_task_spec.rb +99 -0
- metadata +69 -7
data/spec/release_spec.rb
CHANGED
@@ -1,123 +1,251 @@
|
|
1
1
|
describe Bosh::Workspace::Release do
|
2
|
-
|
2
|
+
include Bosh::Workspace::GitCredenialsHelper
|
3
|
+
let(:name) { "foo" }
|
4
|
+
let(:release) { load_release(release_data) }
|
3
5
|
let(:version) { 3 }
|
4
|
-
let(:repo) { extracted_asset_dir("foo", "foo-boshrelease-repo.zip") }
|
5
6
|
let(:release_data) { { "name" => name, "version" => version, "git" => repo } }
|
6
7
|
let(:releases_dir) { File.join(asset_dir("manifests-repo"), ".releases") }
|
7
|
-
let(:release) { Bosh::Workspace::Release.new release_data, releases_dir }
|
8
8
|
let(:templates) { Dir[File.join(releases_dir, name, "templates/*.yml")].to_s }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def load_release(release_data)
|
11
|
+
Bosh::Workspace::Release.new(release_data, releases_dir).tap do |r|
|
12
|
+
fetch_or_clone_repo(r.repo_dir, repo)
|
13
|
+
end
|
14
|
+
end
|
15
15
|
|
16
|
-
|
16
|
+
context "given a release with new structure within 'releases' folder" do
|
17
|
+
let(:repo) { extracted_asset_dir("foo", "foo-boshrelease-repo-new-structure.zip") }
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
describe "#update_repo" do
|
20
|
+
subject do
|
21
|
+
Dir[File.join(releases_dir, name, "releases/#{name}/foo*.yml")].to_s
|
20
22
|
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
+
context "latest version" do
|
25
|
+
before { release.update_repo }
|
26
|
+
|
27
|
+
let(:version) { "latest" }
|
28
|
+
|
29
|
+
it "checks out repo" do
|
30
|
+
expect(subject).to match(/foo-11.yml/)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "does not include templates from master" do
|
34
|
+
expect(templates).to_not match(/deployment.yml/)
|
35
|
+
end
|
24
36
|
end
|
25
37
|
end
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
describe "attributes" do
|
40
|
+
subject { release }
|
41
|
+
its(:name) { should eq name }
|
42
|
+
its(:git_url) { should eq repo }
|
43
|
+
its(:repo_dir) { should match(/\/#{name}$/) }
|
44
|
+
its(:manifest_file) { should match(/\/#{name}-#{version}.yml$/) }
|
45
|
+
its(:manifest) { should match "releases/#{name}/#{name}-#{version}.yml$" }
|
46
|
+
its(:name_version) { should eq "#{name}/#{version}" }
|
47
|
+
its(:version) { should eq version }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "given a release with deprecated structure within 'releases' folder" do
|
52
|
+
let(:repo) { extracted_asset_dir("foo", "foo-boshrelease-repo.zip") }
|
53
|
+
|
54
|
+
describe "#update_repo" do
|
55
|
+
subject { Dir[File.join(releases_dir, name, "releases/foo*.yml")].to_s }
|
56
|
+
|
57
|
+
context "latest version" do
|
58
|
+
before { release.update_repo }
|
59
|
+
|
60
|
+
let(:version) { "latest" }
|
61
|
+
|
62
|
+
it "checks out repo" do
|
63
|
+
expect(subject).to match(/foo-11.yml/)
|
64
|
+
end
|
30
65
|
|
31
|
-
|
32
|
-
|
66
|
+
it "does not include templates from master" do
|
67
|
+
expect(templates).to_not match(/deployment.yml/)
|
68
|
+
end
|
33
69
|
end
|
34
70
|
|
35
|
-
|
36
|
-
|
71
|
+
context "specific version" do
|
72
|
+
let(:version) { "11" }
|
73
|
+
before { release.update_repo }
|
74
|
+
|
75
|
+
it "checks out repo" do
|
76
|
+
expect(subject).to match(/foo-11.yml/)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "does not include templates from master" do
|
80
|
+
expect(templates).to_not match(/deployment.yml/)
|
81
|
+
end
|
37
82
|
end
|
38
|
-
end
|
39
83
|
|
40
|
-
|
41
|
-
|
84
|
+
context "specific version" do
|
85
|
+
let(:version) { "2" }
|
42
86
|
|
43
|
-
|
44
|
-
|
45
|
-
|
87
|
+
it "checks out repo" do
|
88
|
+
release.update_repo
|
89
|
+
expect(subject).to match(/foo-2.yml/)
|
90
|
+
end
|
46
91
|
end
|
47
|
-
end
|
48
92
|
|
49
|
-
|
50
|
-
|
51
|
-
|
93
|
+
context "specific ref with latest release" do
|
94
|
+
let(:release_data) do
|
95
|
+
{"name" => name, "version" => "latest", "ref" => "66658", "git" => repo}
|
96
|
+
end
|
97
|
+
|
98
|
+
it "checks out repo" do
|
99
|
+
release.update_repo
|
100
|
+
expect(subject).to match(/foo-2.yml/)
|
101
|
+
expect(subject).to_not match(/foo-3.yml/)
|
102
|
+
end
|
52
103
|
end
|
53
104
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
105
|
+
context "updated version " do
|
106
|
+
let(:version) { "11" }
|
107
|
+
|
108
|
+
it "checks out file with multiple commits" do
|
109
|
+
release.update_repo
|
110
|
+
expect(subject).to match(/foo-11.yml/)
|
111
|
+
end
|
58
112
|
end
|
59
|
-
end
|
60
113
|
|
61
|
-
|
62
|
-
|
114
|
+
context "non existing version " do
|
115
|
+
let(:version) { "12" }
|
63
116
|
|
64
|
-
|
65
|
-
|
66
|
-
|
117
|
+
it "raises an error" do
|
118
|
+
expect { release.update_repo }.
|
119
|
+
to raise_error(/Could not find version/)
|
120
|
+
end
|
67
121
|
end
|
68
|
-
end
|
69
122
|
|
70
|
-
|
71
|
-
|
123
|
+
context "already cloned repo" do
|
124
|
+
before do
|
125
|
+
load_release("name" => name, "version" => 1, "git" => repo).update_repo
|
126
|
+
end
|
72
127
|
|
73
|
-
|
74
|
-
|
75
|
-
to
|
128
|
+
it "version 3" do
|
129
|
+
release.update_repo
|
130
|
+
expect(subject).to match(/foo-3.yml/)
|
131
|
+
end
|
76
132
|
end
|
77
|
-
end
|
78
133
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
134
|
+
context "multiple releases" do
|
135
|
+
let(:version) { "11" }
|
136
|
+
|
137
|
+
before do
|
138
|
+
load_release("name" => "bar", "version" => 2, "git" => repo).update_repo
|
139
|
+
end
|
140
|
+
|
141
|
+
it "version 11" do
|
142
|
+
release.update_repo
|
143
|
+
expect(subject).to match(/foo-11.yml/)
|
144
|
+
expect(templates).to_not match(/deployment.yml/)
|
145
|
+
end
|
84
146
|
end
|
85
147
|
|
86
|
-
|
87
|
-
|
88
|
-
|
148
|
+
context "specific version" do
|
149
|
+
let(:version) { "11" }
|
150
|
+
before { release.update_repo }
|
151
|
+
|
152
|
+
it "checks out repo" do
|
153
|
+
expect(subject).to match(/foo-11.yml/)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "does not include templates from master" do
|
157
|
+
expect(templates).to_not match(/deployment.yml/)
|
158
|
+
end
|
89
159
|
end
|
90
|
-
end
|
91
160
|
|
92
|
-
|
93
|
-
|
161
|
+
context "specific version" do
|
162
|
+
let(:version) { "2" }
|
94
163
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
164
|
+
it "checks out repo" do
|
165
|
+
release.update_repo
|
166
|
+
expect(subject).to match(/foo-2.yml/)
|
167
|
+
end
|
99
168
|
end
|
100
169
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
170
|
+
context "specific ref with latest release" do
|
171
|
+
let(:release_data) do
|
172
|
+
{"name" => name, "version" => "latest", "ref" => "66658", "git" => repo}
|
173
|
+
end
|
174
|
+
|
175
|
+
it "checks out repo" do
|
176
|
+
release.update_repo
|
177
|
+
expect(subject).to match(/foo-2.yml/)
|
178
|
+
expect(subject).to_not match(/foo-3.yml/)
|
179
|
+
end
|
105
180
|
end
|
106
|
-
end
|
107
|
-
end
|
108
181
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
182
|
+
context "updated version " do
|
183
|
+
let(:version) { "11" }
|
184
|
+
|
185
|
+
it "checks out file with multiple commits" do
|
186
|
+
release.update_repo
|
187
|
+
expect(subject).to match(/foo-11.yml/)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "non existing version " do
|
192
|
+
let(:version) { "12" }
|
193
|
+
|
194
|
+
it "raises an error" do
|
195
|
+
expect { release.version }.
|
196
|
+
to raise_error(/Could not find version/)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context "already cloned repo" do
|
201
|
+
before do
|
202
|
+
load_release("name" => name, "version" => 1, "git" => repo).update_repo
|
203
|
+
end
|
119
204
|
|
120
|
-
|
121
|
-
|
205
|
+
it "version 3" do
|
206
|
+
release.update_repo
|
207
|
+
expect(subject).to match(/foo-3.yml/)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context "multiple releases" do
|
212
|
+
let(:version) { "11" }
|
213
|
+
|
214
|
+
before do
|
215
|
+
load_release("name" => "bar", "version" => 2, "git" => repo).update_repo
|
216
|
+
end
|
217
|
+
|
218
|
+
it "version 11" do
|
219
|
+
release.update_repo
|
220
|
+
expect(subject).to match(/foo-11.yml/)
|
221
|
+
expect(templates).to_not match(/deployment.yml/)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "new release in already cloned repo" do
|
226
|
+
let(:version) { "12" }
|
227
|
+
|
228
|
+
before do
|
229
|
+
load_release("name" => name, "version" => 1, "git" => repo).update_repo
|
230
|
+
extracted_asset_dir("foo", "foo-boshrelease-repo-updated.zip")
|
231
|
+
end
|
232
|
+
|
233
|
+
it "version 12" do
|
234
|
+
release.update_repo
|
235
|
+
expect(subject).to match(/foo-12.yml/)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "attributes" do
|
241
|
+
subject { release }
|
242
|
+
its(:name) { should eq name }
|
243
|
+
its(:git_url) { should eq repo }
|
244
|
+
its(:repo_dir) { should match(/\/#{name}$/) }
|
245
|
+
its(:manifest_file) { should match(/\/#{name}-#{version}.yml$/) }
|
246
|
+
its(:manifest) { should match "releases/#{name}-#{version}.yml$" }
|
247
|
+
its(:name_version) { should eq "#{name}/#{version}" }
|
248
|
+
its(:version) { should eq version }
|
249
|
+
end
|
122
250
|
end
|
123
251
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bosh::Workspace::Schemas
|
2
|
+
describe Credentials do
|
3
|
+
let(:username_password) do
|
4
|
+
{ "url" => "foo", "username" => "bar", "password" => "baz" }
|
5
|
+
end
|
6
|
+
let(:ssh_key) do
|
7
|
+
{ "url" => "bar", "private_key" => "foobarkey" }
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { Credentials.new.validate(credentials) }
|
11
|
+
|
12
|
+
context "valid credentials" do
|
13
|
+
let(:credentials) { [username_password, ssh_key] }
|
14
|
+
it { expect { subject }.to_not raise_error }
|
15
|
+
end
|
16
|
+
|
17
|
+
%w(url username password private_key).each do |field_name|
|
18
|
+
context "missing #{field_name}" do
|
19
|
+
let(:credentials) do
|
20
|
+
[username_password, ssh_key].map do |c|
|
21
|
+
c.delete_if { |k| k == field_name }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
it { expect { subject }.to raise_error(/doesn't validate/i) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Bosh::Workspace::Schemas
|
2
|
+
describe DeploymentPatch do
|
3
|
+
before do
|
4
|
+
allow_any_instance_of(Releases).to receive(:validate).with(:releases)
|
5
|
+
allow_any_instance_of(Stemcells).to receive(:validate).with(:stemcells)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:deployment_patch) do
|
9
|
+
{
|
10
|
+
"stemcells" => :stemcells,
|
11
|
+
"releases" => :releases,
|
12
|
+
"templates_ref" => "477d1228a9f27815d6df3ab977235ab26eecbba6"
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { DeploymentPatch.new.validate(deployment_patch) }
|
17
|
+
|
18
|
+
%w(stemcells releases).each do |field|
|
19
|
+
context "missing #{field}" do
|
20
|
+
before { deployment_patch.delete field }
|
21
|
+
it { expect { subject }.to raise_error(/#{field}.*missing/i) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "optional templates_ref" do
|
26
|
+
before { deployment_patch.delete "templates_ref" }
|
27
|
+
it { expect { subject }.to_not raise_error }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Bosh::Workspace::Schemas
|
2
|
+
describe ProjectDeployment do
|
3
|
+
before do
|
4
|
+
allow_any_instance_of(Releases).to receive(:validate).with(:releases)
|
5
|
+
allow_any_instance_of(Stemcells).to receive(:validate).with(:stemcells)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:project_deployment) do
|
9
|
+
{
|
10
|
+
"name" => "foo",
|
11
|
+
"director_uuid" => "e55134c3-0a63-47be-8409-c9e53e965d5c",
|
12
|
+
"stemcells" => :stemcells,
|
13
|
+
"releases" => :releases,
|
14
|
+
"templates" => [ "foo/bar.yml" ],
|
15
|
+
"meta" => { "foo" => "bar" }
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
subject { ProjectDeployment.new.validate(project_deployment) }
|
20
|
+
|
21
|
+
%w(name director_uuid releases templates meta stemcells).each do |field|
|
22
|
+
context "missing #{field}" do
|
23
|
+
before { project_deployment.delete field }
|
24
|
+
it { expect { subject }.to raise_error(/#{field}.*missing/i) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "optional domain_name" do
|
29
|
+
before { project_deployment["domain_name"] = "example.com" }
|
30
|
+
it { expect { subject }.to_not raise_error }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "director_uuid" do
|
34
|
+
context "invalid" do
|
35
|
+
before { project_deployment["director_uuid"] = "invalid_uuid" }
|
36
|
+
it { expect { subject }.to raise_error(/director_uuid.*doesn't validate/) }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "current" do
|
40
|
+
before { project_deployment["director_uuid"] = "current" }
|
41
|
+
it { expect { subject }.to_not raise_error }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bosh::Workspace::Schemas
|
2
|
+
describe Releases do
|
3
|
+
let(:release) do
|
4
|
+
{"name" => "foo", "version" => 1, "ref" => "cec3ec1", "git" => "example.com/git.git"}
|
5
|
+
end
|
6
|
+
|
7
|
+
subject { Releases.new.validate(releases) }
|
8
|
+
|
9
|
+
%w(name version git).each do |field_name|
|
10
|
+
context "missing #{field_name}" do
|
11
|
+
let(:releases) { [release.delete_if { |k| k == field_name }] }
|
12
|
+
it { expect { subject }.to raise_error(/#{field_name}.*missing/i) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "latest version" do
|
17
|
+
let(:releases) { release["version"] = "latest"; [release] }
|
18
|
+
it { expect { subject }.to_not raise_error }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "invalid version" do
|
22
|
+
let(:releases) { release["version"] = "foo"; [release] }
|
23
|
+
it { expect { subject }.to raise_error(/version.*doesn't validate/i) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "optional ref" do
|
27
|
+
let(:releases) { [release.delete_if { |k| k == "ref" }] }
|
28
|
+
it { expect { subject }.to_not raise_error }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bosh::Workspace::Schemas
|
2
|
+
describe Stemcells do
|
3
|
+
let(:stemcell) do
|
4
|
+
{"name" => "foo", "version" => 1}
|
5
|
+
end
|
6
|
+
|
7
|
+
subject { Stemcells.new.validate(stemcells) }
|
8
|
+
|
9
|
+
%w(name version).each do |field_name|
|
10
|
+
context "missing #{field_name}" do
|
11
|
+
let(:stemcells) { [stemcell.delete_if { |k| k == field_name }] }
|
12
|
+
it { expect { subject }.to raise_error(/#{field_name}.*missing/i) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "latest version" do
|
17
|
+
let(:stemcells) { stemcell["version"] = "latest"; [stemcell] }
|
18
|
+
it { expect { subject }.to_not raise_error }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "patch version string" do
|
22
|
+
let(:stemcells) { stemcell["version"] = "2719.1"; [stemcell] }
|
23
|
+
it { expect { subject }.to_not raise_error }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "patch version float" do
|
27
|
+
let(:stemcells) { stemcell["version"] = 2719.1; [stemcell] }
|
28
|
+
it { expect { subject }.to_not raise_error }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "invalid version" do
|
32
|
+
let(:stemcells) { stemcell["version"] = "foo"; [stemcell] }
|
33
|
+
it { expect { subject }.to raise_error(/version.*should match/i) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/spec/shell_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
describe Shell do
|
3
|
+
subject { Shell.new(stdout) }
|
4
|
+
let(:stdout) { StringIO.new }
|
5
|
+
|
6
|
+
describe '#run' do
|
7
|
+
it 'shells out, prints and returns the output of the command' do
|
8
|
+
expect(subject.run('echo hello; echo world')).to eq("hello\nworld")
|
9
|
+
expect(stdout.string).to eq("hello\nworld\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'shells out with specified additional env variables' do
|
13
|
+
stub_const('ENV', 'SHELL' => '/bin/bash')
|
14
|
+
expect(subject.run('env env', env: { 'VAR' => '123' })).to include('VAR=123')
|
15
|
+
expect(stdout.string).to include('VAR=123')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'shells out with specified additional env variables even when SHELL env variable is not available' do
|
19
|
+
stub_const('ENV', {})
|
20
|
+
expect(subject.run('env env', env: { 'VAR' => '123' })).to include('VAR=123')
|
21
|
+
expect(stdout.string).to include('VAR=123')
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when "output_command" is specified' do
|
25
|
+
it 'outputs the command' do
|
26
|
+
subject.run('echo 1;echo 2;echo 3;echo 4;echo 5', output_command: true)
|
27
|
+
expect(stdout.string).to include('echo 1;echo 2;echo 3;echo 4;echo 5')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when "last_number" is specified' do
|
32
|
+
it 'tails "last_number" lines of output' do
|
33
|
+
cmd = 'echo 1;echo 2;echo 3;echo 4;echo 5'
|
34
|
+
expect(subject.run(cmd, last_number: 3)).to eq("3\n4\n5")
|
35
|
+
expect(stdout.string).to eq("1\n2\n3\n4\n5\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'outputs the entire output if more lines are requested than generated' do
|
39
|
+
cmd = 'echo 1;echo 2;echo 3;echo 4;echo 5'
|
40
|
+
expect(subject.run(cmd, last_number: 6)).to eq("1\n2\n3\n4\n5")
|
41
|
+
expect(stdout.string).to eq("1\n2\n3\n4\n5\n")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when the command fails' do
|
46
|
+
it 'raises an error' do
|
47
|
+
expect {
|
48
|
+
subject.run('false')
|
49
|
+
}.to raise_error /Failed: 'false' from /
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'because the working directory has gone missing' do
|
53
|
+
it 'fails gracefully with a slightly helpful error message' do
|
54
|
+
allow(Dir).to receive(:pwd).and_raise(Errno::ENOENT, 'No such file or directory - getcwd')
|
55
|
+
expect {
|
56
|
+
subject.run('false')
|
57
|
+
}.to raise_error /from a deleted directory/
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'and ignoring failures' do
|
62
|
+
it 'raises an error' do
|
63
|
+
subject.run('false', ignore_failures: true)
|
64
|
+
expect(stdout.string).to match(/continuing anyway/)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -19,8 +19,11 @@ require "archive/zip"
|
|
19
19
|
require "cli"
|
20
20
|
|
21
21
|
require "bosh/workspace"
|
22
|
+
require "bosh/workspace/tasks"
|
22
23
|
|
23
24
|
RSpec.configure do |config|
|
25
|
+
config.filter_run focus: true
|
26
|
+
config.run_all_when_everything_filtered = true
|
24
27
|
config.raise_errors_for_deprecations!
|
25
28
|
config.expect_with :rspec do |c|
|
26
29
|
c.syntax = :expect
|
@@ -28,7 +31,7 @@ RSpec.configure do |config|
|
|
28
31
|
end
|
29
32
|
|
30
33
|
# load all files in spec/support/* (but not lower down)
|
31
|
-
Dir[File.dirname(__FILE__) + '/support
|
34
|
+
Dir[File.dirname(__FILE__) + '/support/*/*.rb'].each do |path|
|
32
35
|
require path unless File.directory?(path)
|
33
36
|
end
|
34
37
|
|
@@ -81,9 +84,12 @@ end
|
|
81
84
|
def extracted_asset_dir(name, *path)
|
82
85
|
zipped_file = asset_dir(*path)
|
83
86
|
target_dir = File.expand_path("../../tmp/#{name}", __FILE__)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
87
|
+
FileUtils.rm_rf(target_dir) if File.exist?(target_dir)
|
88
|
+
FileUtils.mkdir_p(target_dir)
|
89
|
+
Archive::Zip.extract(zipped_file, target_dir)
|
88
90
|
target_dir
|
89
91
|
end
|
92
|
+
|
93
|
+
def project_root
|
94
|
+
File.expand_path('../../', __FILE__)
|
95
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "rake"
|
2
|
+
|
3
|
+
shared_context "rake" do
|
4
|
+
let(:rake) { Rake::Application.new }
|
5
|
+
let(:task_name) { self.class.top_level_description }
|
6
|
+
let(:task_path) { "lib/bosh/workspace/tasks/#{task_name.split(":").first}" }
|
7
|
+
|
8
|
+
def loaded_files_excluding_current_rake_file
|
9
|
+
$".reject { |file| file == File.join(project_root, "#{task_path}.rake") }
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear_main_instance_vars
|
13
|
+
TOPLEVEL_BINDING.eval('self').instance_variables.each do |var|
|
14
|
+
TOPLEVEL_BINDING.eval('self').remove_instance_variable(var)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup_already_invoked_tasks
|
19
|
+
if defined? already_invoked_tasks
|
20
|
+
rake.instance_variable_get(:@tasks).each do |name, task|
|
21
|
+
if already_invoked_tasks.include? name
|
22
|
+
task.instance_variable_set(:@already_invoked, true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
before do
|
29
|
+
Rake.application = rake
|
30
|
+
Rake.application.rake_require(task_path, [project_root], loaded_files_excluding_current_rake_file)
|
31
|
+
setup_already_invoked_tasks
|
32
|
+
end
|
33
|
+
|
34
|
+
after do
|
35
|
+
clear_main_instance_vars
|
36
|
+
end
|
37
|
+
end
|