chef-dk 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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/chef-dk/builtin_commands.rb +10 -0
- data/lib/chef-dk/command/base.rb +2 -2
- data/lib/chef-dk/command/clean_policy_cookbooks.rb +116 -0
- data/lib/chef-dk/command/clean_policy_revisions.rb +113 -0
- data/lib/chef-dk/command/delete_policy.rb +122 -0
- data/lib/chef-dk/command/delete_policy_group.rb +122 -0
- data/lib/chef-dk/command/export.rb +3 -3
- data/lib/chef-dk/command/generate.rb +8 -0
- data/lib/chef-dk/command/generator_commands/app.rb +1 -1
- data/lib/chef-dk/command/generator_commands/cookbook.rb +1 -1
- data/lib/chef-dk/command/generator_commands/policyfile.rb +1 -1
- data/lib/chef-dk/command/generator_commands/repo.rb +1 -1
- data/lib/chef-dk/command/install.rb +22 -5
- data/lib/chef-dk/command/provision.rb +0 -4
- data/lib/chef-dk/command/push.rb +1 -2
- data/lib/chef-dk/command/shell_init.rb +65 -6
- data/lib/chef-dk/command/show_policy.rb +1 -2
- data/lib/chef-dk/command/undelete.rb +155 -0
- data/lib/chef-dk/command/update.rb +5 -5
- data/lib/chef-dk/command/verify.rb +61 -17
- data/lib/chef-dk/completions/bash.sh.erb +5 -0
- data/lib/chef-dk/completions/chef.fish.erb +10 -0
- data/lib/chef-dk/completions/zsh.zsh.erb +21 -0
- data/lib/chef-dk/exceptions.rb +12 -0
- data/lib/chef-dk/helpers.rb +17 -0
- data/lib/chef-dk/policyfile/community_cookbook_source.rb +0 -3
- data/lib/chef-dk/policyfile/lister.rb +3 -1
- data/lib/chef-dk/policyfile/undo_record.rb +142 -0
- data/lib/chef-dk/policyfile/undo_stack.rb +130 -0
- data/lib/chef-dk/policyfile_lock.rb +30 -0
- data/lib/chef-dk/policyfile_services/clean_policies.rb +5 -4
- data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +125 -0
- data/lib/chef-dk/policyfile_services/rm_policy.rb +142 -0
- data/lib/chef-dk/policyfile_services/rm_policy_group.rb +86 -0
- data/lib/chef-dk/policyfile_services/show_policy.rb +1 -1
- data/lib/chef-dk/policyfile_services/undelete.rb +108 -0
- data/lib/chef-dk/service_exceptions.rb +11 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +6 -2
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +1 -1
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +1 -1
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +1 -1
- data/lib/chef-dk/version.rb +1 -1
- data/lib/kitchen/provisioner/policyfile_zero.rb +4 -1
- data/spec/unit/command/base_spec.rb +26 -1
- data/spec/unit/command/clean_policy_cookbooks_spec.rb +181 -0
- data/spec/unit/command/clean_policy_revisions_spec.rb +181 -0
- data/spec/unit/command/delete_policy_group_spec.rb +207 -0
- data/spec/unit/command/delete_policy_spec.rb +207 -0
- data/spec/unit/command/generate_spec.rb +41 -1
- data/spec/unit/command/generator_commands/cookbook_spec.rb +1 -1
- data/spec/unit/command/generator_commands/policyfile_spec.rb +1 -1
- data/spec/unit/command/install_spec.rb +24 -0
- data/spec/unit/command/shell_init_spec.rb +176 -5
- data/spec/unit/command/undelete_spec.rb +246 -0
- data/spec/unit/helpers_spec.rb +24 -0
- data/spec/unit/policyfile/lister_spec.rb +16 -0
- data/spec/unit/policyfile/undo_record_spec.rb +260 -0
- data/spec/unit/policyfile/undo_stack_spec.rb +266 -0
- data/spec/unit/policyfile_lock_serialization_spec.rb +41 -0
- data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +275 -0
- data/spec/unit/policyfile_services/rm_policy_group_spec.rb +241 -0
- data/spec/unit/policyfile_services/rm_policy_spec.rb +266 -0
- data/spec/unit/policyfile_services/show_policy_spec.rb +52 -2
- data/spec/unit/policyfile_services/undelete_spec.rb +304 -0
- metadata +43 -91
data/spec/unit/helpers_spec.rb
CHANGED
@@ -64,5 +64,29 @@ describe ChefDK::Helpers do
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
+
context 'using usr_bin_prefix' do
|
68
|
+
before do
|
69
|
+
stub_const('RUBY_PLATFORM', ruby_platform_string)
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'on Mac' do
|
73
|
+
let(:ruby_platform_string) { 'x86_64-darwin12.0' }
|
74
|
+
|
75
|
+
it 'uses /usr/local/bin' do
|
76
|
+
expect(helpers.usr_bin_prefix).to eq('/usr/local/bin')
|
77
|
+
expect(helpers.usr_bin_path('berks')).to eq('/usr/local/bin/berks')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'on other systems' do
|
82
|
+
let(:ruby_platform_string) { 'x86_64-linux' }
|
83
|
+
|
84
|
+
it 'uses /usr/bin' do
|
85
|
+
expect(helpers.usr_bin_prefix).to eq('/usr/bin')
|
86
|
+
expect(helpers.usr_bin_path('berks')).to eq('/usr/bin/berks')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
67
91
|
end
|
68
92
|
end
|
@@ -248,6 +248,22 @@ describe ChefDK::Policyfile::Lister do
|
|
248
248
|
expect(map["cache"].revision_ids_by_group).to eq(cache_rev_ids)
|
249
249
|
end
|
250
250
|
|
251
|
+
context "when the server has an empty group" do
|
252
|
+
|
253
|
+
let(:dev_group_data) do
|
254
|
+
{
|
255
|
+
"uri" => api_url("policy_groups/dev")
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
259
|
+
# Regression test: this exercises the case where the policy group data
|
260
|
+
# from the server has no "policies" key, which previously caused a NoMethodError.
|
261
|
+
it "correctly lists groups without policies" do
|
262
|
+
expect(info_fetcher.policies_by_group["dev"]).to eq({})
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
251
267
|
end
|
252
268
|
|
253
269
|
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2015 Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'spec_helper'
|
19
|
+
require 'chef-dk/policyfile/undo_record'
|
20
|
+
|
21
|
+
describe ChefDK::Policyfile::UndoRecord do
|
22
|
+
|
23
|
+
subject(:undo_record) { described_class.new }
|
24
|
+
|
25
|
+
let(:policy_revision) do
|
26
|
+
{
|
27
|
+
"name" => "appserver",
|
28
|
+
"revision_id" => "1111111111111111111111111111111111111111111111111111111111111111"
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when empty" do
|
33
|
+
|
34
|
+
it "has an empty description" do
|
35
|
+
expect(undo_record.description).to eq("")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "has an empty set of policy groups" do
|
39
|
+
expect(undo_record.policy_groups).to eq([])
|
40
|
+
end
|
41
|
+
|
42
|
+
it "has an empty set of policy revisions" do
|
43
|
+
expect(undo_record.policy_revisions).to eq([])
|
44
|
+
end
|
45
|
+
|
46
|
+
it "converts to a serializable data structure" do
|
47
|
+
expected = {
|
48
|
+
"format_version" => 1,
|
49
|
+
"description" => "",
|
50
|
+
"backup_data" => {
|
51
|
+
"policy_groups" => [],
|
52
|
+
"policy_revisions" => []
|
53
|
+
}
|
54
|
+
}
|
55
|
+
expect(undo_record.for_serialization).to eq(expected)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with policy data" do
|
60
|
+
|
61
|
+
before do
|
62
|
+
undo_record.description = "delete-policy-group preprod"
|
63
|
+
undo_record.add_policy_group("preprod")
|
64
|
+
undo_record.add_policy_revision("appserver", "preprod", policy_revision)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "has a description" do
|
68
|
+
expect(undo_record.description).to eq("delete-policy-group preprod")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "has a policy group" do
|
72
|
+
expect(undo_record.policy_groups).to eq( [ "preprod" ] )
|
73
|
+
end
|
74
|
+
|
75
|
+
it "has a policy revision" do
|
76
|
+
expect(undo_record.policy_revisions.size).to eq(1)
|
77
|
+
revision_info = undo_record.policy_revisions.first
|
78
|
+
expect(revision_info.policy_name).to eq("appserver")
|
79
|
+
expect(revision_info.policy_group).to eq("preprod")
|
80
|
+
expect(revision_info.data).to eq(policy_revision)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "converts to a serializable data structure" do
|
84
|
+
expected = {
|
85
|
+
"format_version" => 1,
|
86
|
+
"description" => "delete-policy-group preprod",
|
87
|
+
"backup_data" => {
|
88
|
+
"policy_groups" => [ "preprod" ],
|
89
|
+
"policy_revisions" => [
|
90
|
+
{
|
91
|
+
"policy_name" => "appserver",
|
92
|
+
"policy_group" => "preprod",
|
93
|
+
"data" => policy_revision
|
94
|
+
}
|
95
|
+
]
|
96
|
+
}
|
97
|
+
}
|
98
|
+
expect(undo_record.for_serialization).to eq(expected)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "loading from serialized data" do
|
104
|
+
|
105
|
+
context "with invalid data" do
|
106
|
+
|
107
|
+
context "with an invalid object type" do
|
108
|
+
|
109
|
+
let(:serialized_data) { [] }
|
110
|
+
|
111
|
+
it "raises an error" do
|
112
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when required top-level keys aren't present" do
|
118
|
+
|
119
|
+
let(:serialized_data) { {} }
|
120
|
+
|
121
|
+
it "raises an error" do
|
122
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
context "when backup_data is an invalid type" do
|
128
|
+
|
129
|
+
let(:serialized_data) do
|
130
|
+
{
|
131
|
+
"format_version" => 1,
|
132
|
+
"description" => "delete-policy-group preprod",
|
133
|
+
"backup_data" => []
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
it "raises an error" do
|
138
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when backup_data is missing required fields" do
|
144
|
+
|
145
|
+
let(:serialized_data) do
|
146
|
+
{
|
147
|
+
"format_version" => 1,
|
148
|
+
"description" => "delete-policy-group preprod",
|
149
|
+
"backup_data" => {}
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
it "raises an error" do
|
154
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
context "when backup_data has invalid policy_groups data" do
|
160
|
+
|
161
|
+
let(:serialized_data) do
|
162
|
+
{
|
163
|
+
"format_version" => 1,
|
164
|
+
"description" => "delete-policy-group preprod",
|
165
|
+
"backup_data" => {
|
166
|
+
"policy_groups" => nil,
|
167
|
+
"policy_revisions" => []
|
168
|
+
}
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
it "raises an error" do
|
173
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
context "when backup_data has and invalid type for policy_revisions" do
|
179
|
+
|
180
|
+
let(:serialized_data) do
|
181
|
+
{
|
182
|
+
"format_version" => 1,
|
183
|
+
"description" => "delete-policy-group preprod",
|
184
|
+
"backup_data" => {
|
185
|
+
"policy_groups" => [],
|
186
|
+
"policy_revisions" => nil
|
187
|
+
}
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
it "raises an error" do
|
192
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
context "when the backup_data has an invalid item in policy revisions" do
|
198
|
+
|
199
|
+
let(:serialized_data) do
|
200
|
+
{
|
201
|
+
"format_version" => 1,
|
202
|
+
"description" => "delete-policy-group preprod",
|
203
|
+
"backup_data" => {
|
204
|
+
"policy_groups" => [],
|
205
|
+
"policy_revisions" => [ nil ]
|
206
|
+
}
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
it "raises an error" do
|
211
|
+
expect { undo_record.load(serialized_data) }.to raise_error(ChefDK::InvalidUndoRecord)
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "with valid data" do
|
218
|
+
let(:serialized_data) do
|
219
|
+
{
|
220
|
+
"format_version" => 1,
|
221
|
+
"description" => "delete-policy-group preprod",
|
222
|
+
"backup_data" => {
|
223
|
+
"policy_groups" => [ "preprod" ],
|
224
|
+
"policy_revisions" => [
|
225
|
+
{
|
226
|
+
"policy_name" => "appserver",
|
227
|
+
"policy_group" => "preprod",
|
228
|
+
"data" => policy_revision
|
229
|
+
}
|
230
|
+
]
|
231
|
+
}
|
232
|
+
}
|
233
|
+
end
|
234
|
+
|
235
|
+
before do
|
236
|
+
undo_record.load(serialized_data)
|
237
|
+
end
|
238
|
+
|
239
|
+
it "has a policy group" do
|
240
|
+
expect(undo_record.policy_groups).to eq( [ "preprod" ] )
|
241
|
+
end
|
242
|
+
|
243
|
+
it "has a policy revision" do
|
244
|
+
expect(undo_record.policy_revisions.size).to eq(1)
|
245
|
+
revision_info = undo_record.policy_revisions.first
|
246
|
+
expect(revision_info.policy_name).to eq("appserver")
|
247
|
+
expect(revision_info.policy_group).to eq("preprod")
|
248
|
+
expect(revision_info.data).to eq(policy_revision)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "converts to a serializable data structure" do
|
252
|
+
expect(undo_record.for_serialization).to eq(serialized_data)
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
@@ -0,0 +1,266 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2015 Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'spec_helper'
|
19
|
+
require 'chef-dk/policyfile/undo_stack'
|
20
|
+
|
21
|
+
describe ChefDK::Policyfile::UndoStack do
|
22
|
+
|
23
|
+
let(:chefdk_home) { File.join(tempdir, "chefdk_home", ".chefdk") }
|
24
|
+
|
25
|
+
let(:policy_revision) do
|
26
|
+
{
|
27
|
+
"name" => "appserver",
|
28
|
+
"revision_id" => "1111111111111111111111111111111111111111111111111111111111111111"
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:undo_record) do
|
33
|
+
ChefDK::Policyfile::UndoRecord.new.tap do |undo_record|
|
34
|
+
undo_record.add_policy_group("preprod")
|
35
|
+
undo_record.add_policy_revision("appserver", "preprod", policy_revision)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Probably takes a Chef::Config as an arg?
|
40
|
+
subject(:undo_stack) { described_class.new }
|
41
|
+
|
42
|
+
let(:expected_undo_dir) { File.join(chefdk_home, "undo") }
|
43
|
+
|
44
|
+
def undo_stack_files
|
45
|
+
Dir[File.join(expected_undo_dir, "*")]
|
46
|
+
end
|
47
|
+
|
48
|
+
before do
|
49
|
+
clear_tempdir
|
50
|
+
allow(ChefDK::Helpers).to receive(:chefdk_home).and_return(chefdk_home)
|
51
|
+
end
|
52
|
+
|
53
|
+
after(:all) do
|
54
|
+
clear_tempdir
|
55
|
+
end
|
56
|
+
|
57
|
+
it "uses chefdk_home to infer the location of the undo directory" do
|
58
|
+
expect(undo_stack.undo_dir).to eq(expected_undo_dir)
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when there are no undo records" do
|
62
|
+
|
63
|
+
it "has zero items" do
|
64
|
+
expect(undo_stack.size).to eq(0)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "is empty" do
|
68
|
+
expect(undo_stack).to be_empty
|
69
|
+
end
|
70
|
+
|
71
|
+
it "has no items to iterate over" do
|
72
|
+
expect { |b| undo_stack.each_with_id(&b) }.to_not yield_control
|
73
|
+
end
|
74
|
+
|
75
|
+
it "has an empty list of undo records" do
|
76
|
+
expect(undo_stack.undo_records).to eq([])
|
77
|
+
end
|
78
|
+
|
79
|
+
it "raises an error when attempting to pop an item from the stack" do
|
80
|
+
expect { undo_stack.pop }.to raise_error(ChefDK::CantUndo)
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "pushing an undo record" do
|
84
|
+
|
85
|
+
before do
|
86
|
+
expect(File.exist?(chefdk_home)).to be(false)
|
87
|
+
expect(File.exist?(expected_undo_dir)).to be(false)
|
88
|
+
|
89
|
+
undo_stack.push(undo_record)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "creates the undo directory" do
|
93
|
+
expect(File.exist?(chefdk_home)).to be(true)
|
94
|
+
expect(File.exist?(expected_undo_dir)).to be(true)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "creates the undo record" do
|
98
|
+
expect(undo_stack_files.size).to eq(1)
|
99
|
+
|
100
|
+
undo_record_json = IO.read(undo_stack_files.first)
|
101
|
+
undo_record_data = FFI_Yajl::Parser.parse(undo_record_json)
|
102
|
+
expect(undo_record_data).to eq(undo_record.for_serialization)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context "when there is one undo record" do
|
110
|
+
|
111
|
+
# `Time.new` is stubbed later on, need to force it to be evaluated before
|
112
|
+
# then.
|
113
|
+
let!(:start_time) { Time.new }
|
114
|
+
|
115
|
+
let(:expected_id) { start_time.utc.strftime("%Y%m%d%H%M%S") }
|
116
|
+
|
117
|
+
let(:missing_id) { (start_time + 1).utc.strftime("%Y%m%d%H%M%S") }
|
118
|
+
|
119
|
+
before do
|
120
|
+
allow(Time).to receive(:new).and_return(start_time)
|
121
|
+
undo_stack.push(undo_record)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "creates the item on disk" do
|
125
|
+
expect(File).to be_directory(undo_stack.undo_dir)
|
126
|
+
expect(undo_stack_files.size).to eq(1)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "has one item" do
|
130
|
+
expect(undo_stack.size).to eq(1)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "is not empty" do
|
134
|
+
expect(undo_stack).to_not be_empty
|
135
|
+
end
|
136
|
+
|
137
|
+
it "checks whether a record exists by id" do
|
138
|
+
expect(undo_stack).to have_id(expected_id)
|
139
|
+
expect(undo_stack).to_not have_id(missing_id)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "deletes a record by id" do
|
143
|
+
expect(undo_stack.delete(expected_id)).to eq(undo_record)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "deletes a record by id and yields it" do
|
147
|
+
expect { |b| undo_stack.delete(expected_id, &b) }.to yield_with_args(undo_record)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "fails to delete a record that doesn't exist" do
|
151
|
+
expect { undo_stack.delete(missing_id) }.to raise_error(ChefDK::UndoRecordNotFound)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "pops the last record" do
|
155
|
+
expect(undo_stack.pop).to eq(undo_record)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "pops the last record and yields it" do
|
159
|
+
expect { |b| undo_stack.pop(&b) }.to yield_with_args(undo_record)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "iterates over the records" do
|
163
|
+
expect { |b| undo_stack.each_with_id(&b) }.to yield_successive_args([expected_id, undo_record])
|
164
|
+
end
|
165
|
+
|
166
|
+
it "has the undo record that was pushed" do
|
167
|
+
expect(undo_stack.undo_records.size).to eq(1)
|
168
|
+
expect(undo_stack.undo_records).to eq( [ undo_record ] )
|
169
|
+
end
|
170
|
+
|
171
|
+
context "and the record is removed" do
|
172
|
+
|
173
|
+
let!(:popped_record) { undo_stack.pop }
|
174
|
+
|
175
|
+
it "has no items" do
|
176
|
+
expect(undo_stack_files.size).to eq(0)
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
context "when the stack is at the maximum configured size" do
|
185
|
+
# `Time.new` is stubbed later on, need to force it to be evaluated before
|
186
|
+
# then.
|
187
|
+
let!(:start_time) { Time.new }
|
188
|
+
|
189
|
+
def next_time
|
190
|
+
@increment ||= 0
|
191
|
+
@increment += 1
|
192
|
+
|
193
|
+
start_time + @increment
|
194
|
+
end
|
195
|
+
|
196
|
+
def incremented_undo_record(i)
|
197
|
+
record = {
|
198
|
+
"name" => "appserver",
|
199
|
+
"revision_id" => i.to_s * 64
|
200
|
+
}
|
201
|
+
|
202
|
+
ChefDK::Policyfile::UndoRecord.new.tap do |undo_record|
|
203
|
+
undo_record.description = "delete-policy-group preprod-#{i}"
|
204
|
+
undo_record.add_policy_group("preprod-#{i}")
|
205
|
+
undo_record.add_policy_revision("appserver", "preprod-#{i}", record)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
before do
|
210
|
+
## # UndoStack assumes you're not creating more than 1 undo record/second,
|
211
|
+
## # which is reasonable in the real world but won't work here.
|
212
|
+
allow(Time).to receive(:new) { next_time }
|
213
|
+
|
214
|
+
10.times { |i| undo_stack.push(incremented_undo_record(i)) }
|
215
|
+
|
216
|
+
expect(undo_stack_files.size).to eq(10)
|
217
|
+
end
|
218
|
+
|
219
|
+
describe "pushing a new undo record" do
|
220
|
+
it "does not exceed the maximum size" do
|
221
|
+
undo_stack.push(incremented_undo_record(11))
|
222
|
+
|
223
|
+
expect(undo_stack_files.size).to eq(10)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "removes the oldest record" do
|
227
|
+
oldest_record_file = undo_stack_files.sort.first
|
228
|
+
|
229
|
+
undo_stack.push(incremented_undo_record(11))
|
230
|
+
|
231
|
+
expect(File.exist?(oldest_record_file)).to be(false)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context "when the stack is above maximum configured size" do
|
236
|
+
|
237
|
+
let(:older_record_path) do
|
238
|
+
record_id = (Time.new - (3600 * 24)).utc.strftime("%Y%m%d%H%M%S")
|
239
|
+
File.join(expected_undo_dir, record_id)
|
240
|
+
end
|
241
|
+
|
242
|
+
before do
|
243
|
+
FileUtils.touch(older_record_path)
|
244
|
+
expect(undo_stack_files.size).to eq(11)
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "pushing a new undo record" do
|
248
|
+
it "does not exceed the maximum size" do
|
249
|
+
undo_stack.push(incremented_undo_record(11))
|
250
|
+
|
251
|
+
expect(undo_stack_files.size).to eq(10)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "removes the oldest record" do
|
255
|
+
oldest_record_file = undo_stack_files.sort.first
|
256
|
+
|
257
|
+
undo_stack.push(incremented_undo_record(11))
|
258
|
+
|
259
|
+
expect(File.exist?(oldest_record_file)).to be(false)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|