aws-codedeploy-agent 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGES.md +3 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +177 -0
  5. data/NOTICE +2 -0
  6. data/README.md +16 -0
  7. data/aws-codedeploy-agent.gemspec +39 -0
  8. data/bin/codedeploy-agent +78 -0
  9. data/bin/codedeploy-install +15 -0
  10. data/bin/codedeploy-uninstall +13 -0
  11. data/certs/host-agent-deployment-signer-ca-chain.pem +76 -0
  12. data/conf/codedeployagent.yml +9 -0
  13. data/init.d/codedeploy-agent +61 -0
  14. data/lib/core_ext.rb +71 -0
  15. data/lib/instance_agent.rb +35 -0
  16. data/lib/instance_agent/agent/base.rb +34 -0
  17. data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +133 -0
  18. data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +163 -0
  19. data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +142 -0
  20. data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +23 -0
  21. data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +23 -0
  22. data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +121 -0
  23. data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +66 -0
  24. data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +134 -0
  25. data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +27 -0
  26. data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +72 -0
  27. data/lib/instance_agent/codedeploy_plugin/command_executor.rb +357 -0
  28. data/lib/instance_agent/codedeploy_plugin/command_poller.rb +146 -0
  29. data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +150 -0
  30. data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +206 -0
  31. data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +374 -0
  32. data/lib/instance_agent/codedeploy_plugin/installer.rb +143 -0
  33. data/lib/instance_agent/codedeploy_plugin/request_helper.rb +28 -0
  34. data/lib/instance_agent/config.rb +43 -0
  35. data/lib/instance_agent/log.rb +3 -0
  36. data/lib/instance_agent/platform.rb +17 -0
  37. data/lib/instance_agent/platform/linux_util.rb +57 -0
  38. data/lib/instance_agent/runner/child.rb +57 -0
  39. data/lib/instance_agent/runner/master.rb +103 -0
  40. data/lib/instance_metadata.rb +47 -0
  41. data/test/certificate_helper.rb +120 -0
  42. data/test/helpers/instance_agent_helper.rb +25 -0
  43. data/test/instance_agent/agent/base_test.rb +49 -0
  44. data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +1710 -0
  45. data/test/instance_agent/codedeploy_plugin/codedeploy_control_test.rb +51 -0
  46. data/test/instance_agent/codedeploy_plugin/command_executor_test.rb +513 -0
  47. data/test/instance_agent/codedeploy_plugin/command_poller_test.rb +459 -0
  48. data/test/instance_agent/codedeploy_plugin/deployment_specification_test.rb +335 -0
  49. data/test/instance_agent/codedeploy_plugin/hook_executor_test.rb +250 -0
  50. data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +566 -0
  51. data/test/instance_agent/codedeploy_plugin/installer_test.rb +519 -0
  52. data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +37 -0
  53. data/test/instance_agent/config_test.rb +64 -0
  54. data/test/instance_agent/runner/child_test.rb +87 -0
  55. data/test/instance_metadata_test.rb +97 -0
  56. data/test/test_helper.rb +16 -0
  57. data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -0
  58. data/vendor/gems/codedeploy-commands/apis/CodeDeployCommand.api.json +372 -0
  59. data/vendor/gems/codedeploy-commands/codedeploy-commands-1.0.0.gemspec +28 -0
  60. data/vendor/gems/codedeploy-commands/lib/aws/codedeploy_commands.rb +18 -0
  61. data/vendor/gems/codedeploy-commands/lib/aws/plugins/certificate_authority.rb +12 -0
  62. data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +22 -0
  63. data/vendor/gems/process_manager/README.md +1 -0
  64. data/vendor/gems/process_manager/lib/blank.rb +153 -0
  65. data/vendor/gems/process_manager/lib/core_ext.rb +73 -0
  66. data/vendor/gems/process_manager/lib/process_manager.rb +49 -0
  67. data/vendor/gems/process_manager/lib/process_manager/child.rb +119 -0
  68. data/vendor/gems/process_manager/lib/process_manager/config.rb +112 -0
  69. data/vendor/gems/process_manager/lib/process_manager/log.rb +107 -0
  70. data/vendor/gems/process_manager/lib/process_manager/master.rb +322 -0
  71. data/vendor/gems/process_manager/process_manager-0.0.13.gemspec +42 -0
  72. data/vendor/specifications/aws-sdk-core-2.0.5.gemspec +39 -0
  73. data/vendor/specifications/builder-3.2.2.gemspec +29 -0
  74. data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +28 -0
  75. data/vendor/specifications/gli-2.5.6.gemspec +51 -0
  76. data/vendor/specifications/jamespath-0.5.1.gemspec +35 -0
  77. data/vendor/specifications/little-plugger-1.1.3.gemspec +32 -0
  78. data/vendor/specifications/logging-1.8.1.gemspec +44 -0
  79. data/vendor/specifications/multi_json-1.7.7.gemspec +30 -0
  80. data/vendor/specifications/multi_json-1.8.4.gemspec +30 -0
  81. data/vendor/specifications/multi_xml-0.5.5.gemspec +30 -0
  82. data/vendor/specifications/process_manager-0.0.13.gemspec +42 -0
  83. data/vendor/specifications/simple_pid-0.2.1.gemspec +28 -0
  84. metadata +377 -0
@@ -0,0 +1,566 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+ require 'fileutils'
4
+
5
+ module InstanceAgent
6
+ module CodeDeployPlugin
7
+ class InstallInstructionTest < InstanceAgentTestCase
8
+ context "parsing an install file" do
9
+ context "a single mapped file" do
10
+ setup do
11
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "copy", "source" => "test_source", "destination" => "test_destination"}]}
12
+ @parse_string = JSON.dump(install_instructions)
13
+ @mock_file = mock
14
+ @mock_file.stubs(:puts)
15
+ @mock_file.stubs(:size).returns(0)
16
+ @mock_file.stubs(:close)
17
+ File.stubs(:open).returns(@mock_file)
18
+ end
19
+
20
+ should "return a collection containing a single CopyCommand which copies from test_source to test_destination" do
21
+ commands = InstallInstruction.parse_install_commands(@parse_string)
22
+ FileUtils.expects(:copy).with("test_source","test_destination", :preserve => true)
23
+ assert_not_equal nil, commands
24
+ commands.each do |command|
25
+ command.execute(@mock_file)
26
+ end
27
+ end
28
+ end
29
+
30
+ context "multiple mapped files" do
31
+ setup do
32
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "copy", "source" => "test_source", "destination" => "test_destination"}, {"type" => "copy", "source" => "source_2", "destination"=>"destination_2"}]}
33
+ @parse_string = JSON.dump(install_instructions)
34
+ @mock_file = mock
35
+ @mock_file.stubs(:puts)
36
+ @mock_file.stubs(:size).returns(0)
37
+ @mock_file.stubs(:close)
38
+ File.stubs(:open).returns(@mock_file)
39
+ end
40
+
41
+ should "return a collection containing multiple copy commands" do
42
+ commands = InstallInstruction.parse_install_commands(@parse_string)
43
+ FileUtils.expects(:copy).with("test_source","test_destination", :preserve => true)
44
+ FileUtils.expects(:copy).with("source_2","destination_2", :preserve => true)
45
+ assert_not_equal nil, commands
46
+ commands.each do |command|
47
+ command.execute(@mock_file)
48
+ end
49
+ end
50
+ end
51
+
52
+ context "contains a mkdir command" do
53
+ setup do
54
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "copy", "source" => "test_source", "destination" => "test_destination"}, {"type" => "mkdir", "directory"=>"directory"}]}
55
+ @parse_string = JSON.dump(install_instructions)
56
+ @mock_file = mock
57
+ @mock_file.stubs(:puts)
58
+ @mock_file.stubs(:size).returns(0)
59
+ @mock_file.stubs(:close)
60
+ @mock_file.stubs(:exist?).returns(false)
61
+ File.stubs(:open).returns(@mock_file)
62
+ File.stubs(:exists?).returns(false)
63
+ end
64
+
65
+ should "return a collection containing a copy command and a mkdir command" do
66
+ commands = InstallInstruction.parse_install_commands(@parse_string)
67
+ FileUtils.expects(:copy).with("test_source","test_destination", :preserve => true)
68
+ FileUtils.expects(:mkdir).with("directory")
69
+ assert_not_equal nil, commands
70
+ commands.each do |command|
71
+ command.execute(@mock_file)
72
+ end
73
+ end
74
+
75
+ should "raise an error if a file exists at the mkdir location" do
76
+ commands = InstallInstruction.parse_install_commands(@parse_string)
77
+ File.stubs(:exists?).with("directory").returns(true)
78
+ FileUtils.stubs(:copy)
79
+
80
+ assert_raised_with_message("File already exists at directory") do
81
+ commands.each do |command|
82
+ command.execute(@mock_file)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ context "correctly determines method from file type" do
89
+ setup do
90
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "copy", "source" => "test_source", "destination" => "test_destination"}, {"type" => "copy", "source" => "source_2", "destination"=>"destination_2"}]}
91
+ @parse_string = JSON.dump(install_instructions)
92
+ @instruction_file = mock
93
+ @instruction_file.stubs(:read).returns(@parse_string)
94
+ @instruction_file.stubs(:path).returns("test/123-install.json")
95
+ @instruction_file.stubs(:close)
96
+ File.stubs(:open).with("test/123-install.json", 'r').returns(@instruction_file)
97
+ end
98
+
99
+ should "call parse_install_commands" do
100
+ InstallInstruction.expects(:parse_install_commands).with(@parse_string)
101
+ commands = InstallInstruction.generate_commands_from_file(@instruction_file)
102
+ end
103
+ end
104
+
105
+ context "contains a chmod command" do
106
+ setup do
107
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "chmod", "mode" => "0740", "file" => "testfile.txt"}]}
108
+ @parse_string = JSON.dump(install_instructions)
109
+ @mock_file = mock
110
+ File.stubs(:chmod)
111
+ end
112
+
113
+ should "set the mode of the object" do
114
+ commands = InstallInstruction.parse_install_commands(@parse_string)
115
+ File.expects(:chmod).with("740".to_i(8), "testfile.txt")
116
+ assert_not_equal nil, commands
117
+ commands.each do |command|
118
+ command.execute(@mock_file)
119
+ end
120
+ end
121
+ end
122
+
123
+ context "contains a chown command" do
124
+ setup do
125
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "chown", "owner" => "bob", "group" => "dev", "file" => "testfile.txt"}]}
126
+ @parse_string = JSON.dump(install_instructions)
127
+ @mock_etc = mock
128
+ @mock_etc.stubs(:gid).returns(222)
129
+ @mock_etc.stubs(:uid).returns(111)
130
+ @mock_file = mock
131
+ Etc.stubs(:getpwnam).with("bob").returns(@mock_etc)
132
+ Etc.stubs(:getgrnam).with("dev").returns(@mock_etc)
133
+ File.stubs(:chchown)
134
+ end
135
+
136
+ should "set the owner of the object" do
137
+ commands = InstallInstruction.parse_install_commands(@parse_string)
138
+ File.expects(:chown).with(111, 222, "testfile.txt")
139
+ assert_not_equal nil, commands
140
+ commands.each do |command|
141
+ command.execute(@mock_file)
142
+ end
143
+ end
144
+ end
145
+
146
+ context "contains a setfacl command" do
147
+ setup do
148
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "setfacl", "acl" => ["user:bob:rwx","default:user:bob:rwx"], "file" => "testfile.txt"}]}
149
+ @parse_string = JSON.dump(install_instructions)
150
+ @mock_file = mock
151
+ @mock_stat = mock
152
+ @mock_stat.stubs(:mode).returns("100421".to_i(8))
153
+ ChangeAclCommand.any_instance.stubs(:system).returns(false)
154
+ @full_acl = "user:bob:rwx,default:user:bob:rwx,user::r--,group::-w-,other::--x,mask::-w-,default:user::r--,default:group::-w-,default:other::--x,default:mask::-w-"
155
+ File.stubs(:stat).returns(@mock_stat)
156
+ end
157
+
158
+ should "set the acl of the object" do
159
+ commands = InstallInstruction.parse_install_commands(@parse_string)
160
+ ChangeAclCommand.any_instance.expects(:system).with("setfacl --set #{@full_acl} testfile.txt").returns(true)
161
+ assert_not_equal nil, commands
162
+ commands.each do |command|
163
+ command.execute(@mock_file)
164
+ end
165
+ end
166
+
167
+ should "throw if system call fails" do
168
+ commands = InstallInstruction.parse_install_commands(@parse_string)
169
+ ChangeAclCommand.any_instance.expects(:system).with("setfacl --set #{@full_acl} testfile.txt").returns(false)
170
+ assert_not_equal nil, commands
171
+ assert_raise(RuntimeError) do
172
+ commands.each do |command|
173
+ command.execute(@mock_file)
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ context "contains a semanage command" do
180
+
181
+ context "with a role" do
182
+ setup do
183
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "semanage", "context" => {"name" => "name", "role" => "role", "type" => "type", "range" => "s0" }, "file" => "testfile.txt"}]}
184
+ @parse_string = JSON.dump(install_instructions)
185
+ ChangeContextCommand.any_instance.stubs(:system).returns(true)
186
+ @mock_file = mock
187
+ end
188
+
189
+ should "raise an exception" do
190
+ assert_raise(RuntimeError) do
191
+ commands = InstallInstruction.parse_install_commands(@parse_string)
192
+ end
193
+ end
194
+ end
195
+
196
+ context "which is valid" do
197
+ setup do
198
+ install_instructions = { "revisionId" => "foo" , "instructions" => [{"type" => "semanage", "context" => {"name" => "name", "role" => nil, "type" => "type", "range" => "s0" }, "file" => "testfile.txt"}]}
199
+ @parse_string = JSON.dump(install_instructions)
200
+ @mock_file = mock
201
+ ChangeContextCommand.any_instance.stubs(:system).returns(false)
202
+ File.stubs(:realpath).returns("testfile.txt")
203
+ end
204
+
205
+ should "set the context of the object" do
206
+ commands = InstallInstruction.parse_install_commands(@parse_string)
207
+ ChangeContextCommand.any_instance.expects(:system).with("semanage fcontext -a -s name -t type -r s0 testfile.txt").returns(true)
208
+ ChangeContextCommand.any_instance.expects(:system).with("restorecon -v testfile.txt").returns(true)
209
+ @mock_file.expects(:puts).with("semanage\0testfile.txt")
210
+ assert_not_equal nil, commands
211
+ commands.each do |command|
212
+ command.execute(@mock_file)
213
+ end
214
+ end
215
+
216
+ should "throw if semanage system call fails" do
217
+ commands = InstallInstruction.parse_install_commands(@parse_string)
218
+ ChangeContextCommand.any_instance.expects(:system).with("semanage fcontext -a -s name -t type -r s0 testfile.txt").returns(false)
219
+ assert_not_equal nil, commands
220
+ assert_raise(RuntimeError) do
221
+ commands.each do |command|
222
+ command.execute(@mock_file)
223
+ end
224
+ end
225
+ end
226
+
227
+ should "throw if system call fails" do
228
+ commands = InstallInstruction.parse_install_commands(@parse_string)
229
+ ChangeContextCommand.any_instance.expects(:system).with("semanage fcontext -a -s name -t type -r s0 testfile.txt").returns(true)
230
+ ChangeContextCommand.any_instance.expects(:system).with("restorecon -v testfile.txt").returns(false)
231
+ assert_not_equal nil, commands
232
+ assert_raise(RuntimeError) do
233
+ commands.each do |command|
234
+ command.execute(@mock_file)
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ context "Parsing a delete file" do
243
+ context "an empty delete file" do
244
+ setup do
245
+ @parse_string = <<-END
246
+ END
247
+ end
248
+
249
+ should "return an empty command collection" do
250
+ commands = InstallInstruction.parse_remove_commands(@parse_string)
251
+ assert_equal 0, commands.length
252
+ end
253
+ end
254
+
255
+ context "a single file to delete" do
256
+ setup do
257
+ @parse_string = <<-END
258
+ test_delete_path
259
+ END
260
+ File.stubs(:exist?).with("test_delete_path").returns(true)
261
+ end
262
+
263
+ should "produce a command that deletes test_delete_path" do
264
+ commands = InstallInstruction.parse_remove_commands(@parse_string)
265
+ FileUtils.expects(:rm).with("test_delete_path")
266
+ assert_not_equal nil, commands
267
+ commands.each do |command|
268
+ command.execute
269
+ end
270
+ end
271
+ end
272
+
273
+ context "multiple files to delete" do
274
+ setup do
275
+ @parse_string = <<-END
276
+ test_delete_path
277
+ another_delete_path
278
+ END
279
+ File.stubs(:directory?).returns(false)
280
+ File.stubs(:exist?).with("test_delete_path").returns(true)
281
+ File.stubs(:exist?).with("another_delete_path").returns(true)
282
+ end
283
+
284
+ should "produce a command that deletes test_delete_path" do
285
+ commands = InstallInstruction.parse_remove_commands(@parse_string)
286
+ FileUtils.expects(:rm).with("test_delete_path")
287
+ FileUtils.expects(:rm).with("another_delete_path")
288
+ assert_not_equal nil, commands
289
+ commands.each do |command|
290
+ command.execute
291
+ end
292
+ end
293
+
294
+ should "use rmdir for directories" do
295
+ File.stubs(:directory?).with("test_delete_path").returns(true)
296
+
297
+ commands = InstallInstruction.parse_remove_commands(@parse_string)
298
+ FileUtils.expects(:rmdir).with("test_delete_path")
299
+ FileUtils.expects(:rm).with("another_delete_path")
300
+
301
+ commands.each do |command|
302
+ command.execute
303
+ end
304
+ end
305
+ end
306
+
307
+ context "removes mangled line at the end" do
308
+ setup do
309
+ @parse_string = <<-END
310
+ test_delete_path
311
+ another_delete_path
312
+ END
313
+ @parse_string << "mangled"
314
+ File.stubs(:exist?).with("test_delete_path").returns(true)
315
+ File.stubs(:exist?).with("another_delete_path").returns(true)
316
+ end
317
+
318
+ should "produce a command that deletes test_delete_path" do
319
+ commands = InstallInstruction.parse_remove_commands(@parse_string)
320
+ FileUtils.expects(:rm).with("test_delete_path")
321
+ FileUtils.expects(:rm).with("another_delete_path")
322
+ FileUtils.expects(:rm).with("mangled").never
323
+ assert_not_equal nil, commands
324
+ commands.each do |command|
325
+ command.execute
326
+ end
327
+ end
328
+ end
329
+
330
+ context "correctly determines method from file type" do
331
+ setup do
332
+ @parse_string = 'foo'
333
+ @instruction_file = mock
334
+ @instruction_file.stubs(:path).returns("test/123-cleanup")
335
+ File.stubs(:open).with("test/123-cleanup", 'r').returns(@instruction_file)
336
+ @instruction_file.stubs(:read).returns(@parse_string)
337
+ @instruction_file.stubs(:close)
338
+ end
339
+
340
+ should "call parse_remove_commands" do
341
+ InstallInstruction.expects(:parse_remove_commands).with(@parse_string)
342
+ commands = InstallInstruction.generate_commands_from_file(@instruction_file)
343
+ end
344
+ end
345
+
346
+ context "with a semanage command" do
347
+ setup do
348
+ @parse_string = "semanage\0testfile.txt\n"
349
+ RemoveContextCommand.any_instance.stubs(:system)
350
+ end
351
+
352
+ should "remove the context of the object" do
353
+ commands = InstallInstruction.parse_remove_commands(@parse_string)
354
+ RemoveContextCommand.any_instance.expects(:system).with("semanage fcontext -d testfile.txt")
355
+ assert_not_equal nil, commands
356
+ commands.each do |command|
357
+ command.execute
358
+ end
359
+ end
360
+ end
361
+ end
362
+
363
+ context "Testing the command builder" do
364
+ setup do
365
+ @command_builder = CommandBuilder.new()
366
+ Dir.chdir "/tmp"
367
+ end
368
+
369
+ should "Have an empty command array" do
370
+ assert_equal @command_builder.command_array, []
371
+ end
372
+
373
+ context "with a single copy command" do
374
+ setup do
375
+ @command_builder = CommandBuilder.new()
376
+ @command_builder.copy("source", "destination")
377
+ @expected_json = {"instructions"=>[{"type"=>"copy","source"=>"source","destination"=>"/tmp/destination"}]}.to_json
378
+ end
379
+
380
+ should "have a single copy in the returned JSON" do
381
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
382
+ end
383
+
384
+ should "raise a duplicate exception when a copy collides with another copy" do
385
+ assert_raised_with_message("Duplicate copy instruction to /tmp/destination from source and source") do
386
+ @command_builder.copy("source", "destination")
387
+ end
388
+ end
389
+ end
390
+
391
+ context "with a single mkdir command" do
392
+ setup do
393
+ @command_builder = CommandBuilder.new()
394
+ @command_builder.mkdir("directory")
395
+ @expected_json = {"instructions"=>[{"type"=>"mkdir","directory"=>"/tmp/directory"}]}.to_json
396
+ end
397
+
398
+ should "have a single mkdir in the returned JSON" do
399
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
400
+ end
401
+
402
+ should "raise a duplicate exception when trying to create a directory collides with a copy" do
403
+ @command_builder.copy("source", "directory/dir1")
404
+ assert_raised_with_message("Duplicate mkdir instruction for /tmp/directory/dir1 which is already being copied from source") do
405
+ @command_builder.mkdir("directory/dir1")
406
+ end
407
+ end
408
+ end
409
+
410
+ context "with one of each command (copy and mkdir)" do
411
+ setup do
412
+ @command_builder = CommandBuilder.new()
413
+ @command_builder.mkdir("directory/target")
414
+ @command_builder.copy( "file_target", "directory/target/file_target")
415
+ end
416
+
417
+ should "raise a duplicate exception when trying to make a copy collides with a mkdir" do
418
+ assert_raised_with_message("Duplicate copy instruction to /tmp/directory/target from target which is already being installed as a directory") do
419
+ @command_builder.copy( "target", "directory/target")
420
+ end
421
+ end
422
+
423
+ should "say it is copying the appropriate file" do
424
+ assert @command_builder.copying_file?("/tmp/directory/target/file_target")
425
+ assert !@command_builder.copying_file?("/tmp/directory/target")
426
+ end
427
+
428
+ should "say it is making the appropriate directory" do
429
+ assert !@command_builder.making_directory?("/tmp/directory/target/file_target")
430
+ assert @command_builder.making_directory?("/tmp/directory/target")
431
+ end
432
+
433
+ should "match the file when appropriate" do
434
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/target", {
435
+ :type => ["file"],
436
+ :pattern => "file*",
437
+ :except => []})
438
+ assert @command_builder.find_matches(permission).include?("/tmp/directory/target/file_target")
439
+
440
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/target", {
441
+ :type => ["directory"],
442
+ :pattern => "file*",
443
+ :except => []})
444
+ assert !@command_builder.find_matches(permission).include?("/tmp/directory/target/file_target")
445
+
446
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/target", {
447
+ :type => ["file"],
448
+ :pattern => "filefile*",
449
+ :except => []})
450
+ assert !@command_builder.find_matches(permission).include?("/tmp/directory/target/file_target")
451
+
452
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/target", {
453
+ :type => ["file"],
454
+ :pattern => "file*",
455
+ :except => ["*target"]})
456
+ assert !@command_builder.find_matches(permission).include?("/tmp/directory/target/file_target")
457
+ end
458
+
459
+ should "match the directory when appropriate" do
460
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/", {
461
+ :type => ["directory"],
462
+ :pattern => "tar*",
463
+ :except => []})
464
+ assert @command_builder.find_matches(permission).include?("/tmp/directory/target")
465
+
466
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/", {
467
+ :type => ["file"],
468
+ :pattern => "tar*",
469
+ :except => []})
470
+ assert !@command_builder.find_matches(permission).include?("/tmp/directory/target")
471
+
472
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/", {
473
+ :type => ["directory"],
474
+ :pattern => "tarr*",
475
+ :except => []})
476
+ assert !@command_builder.find_matches(permission).include?("/tmp/directory/target")
477
+
478
+ permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("/tmp/directory/", {
479
+ :type => ["directory"],
480
+ :pattern => "tar*",
481
+ :except => ["*et"]})
482
+ assert !@command_builder.find_matches(permission).include?("/tmp/directory/target")
483
+ end
484
+ end
485
+
486
+ context "two mkdirs to the same place" do
487
+ setup do
488
+ @command_builder = CommandBuilder.new()
489
+ @command_builder.mkdir("directory")
490
+ @command_builder.mkdir("directory")
491
+ @expected_json = {"instructions"=>[{"type"=>"mkdir","directory"=>"/tmp/directory"}]}.to_json
492
+ end
493
+
494
+ should "have a single mkdir in the returned JSON" do
495
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
496
+ end
497
+ end
498
+
499
+ context "two mkdirs to the same place one has a trailing /" do
500
+ setup do
501
+ @command_builder = CommandBuilder.new()
502
+ @command_builder.mkdir("directory")
503
+ @command_builder.mkdir("directory/")
504
+ @expected_json = {"instructions"=>[{"type"=>"mkdir","directory"=>"/tmp/directory"}]}.to_json
505
+ end
506
+
507
+ should "have a single mkdir in the returned JSON" do
508
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
509
+ end
510
+ end
511
+
512
+ context "setting permissions" do
513
+ should "raise a duplicate exception when trying to set permissions twice" do
514
+ @permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("testfile.txt")
515
+ @command_builder = CommandBuilder.new()
516
+ @command_builder.set_permissions("testfile.txt", @permission)
517
+ assert_raised_with_message("Duplicate permission setting instructions for /tmp/testfile.txt") do
518
+ @command_builder.set_permissions("testfile.txt", @permission)
519
+ end
520
+ end
521
+
522
+ should "not add any commands for empty permissions" do
523
+ @permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("testfile.txt")
524
+ @command_builder = CommandBuilder.new()
525
+ @command_builder.set_permissions("testfile.txt", @permission)
526
+ @expected_json = {"instructions"=>[]}.to_json
527
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
528
+ end
529
+
530
+ should "add commands for each part of permisssions" do
531
+ @permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("testfile.txt", {
532
+ :mode=>InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ModeInfo.new(744),
533
+ :acls=>InstanceAgent::CodeDeployPlugin::ApplicationSpecification::AclInfo.new(["u:bob:7","d:g:dev:4"]),
534
+ :context=>InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ContextInfo.new({"name"=>"name","type"=>"type","range"=>"s2-s3:c0,c2.c4,c6"}),
535
+ :owner=>"bob",
536
+ :group=>"dev"})
537
+ @command_builder = CommandBuilder.new()
538
+ @command_builder.set_permissions("testfile.txt", @permission)
539
+ @expected_json = {"instructions"=>[{"type"=>"chmod","mode"=>"744","file"=>"/tmp/testfile.txt"},
540
+ {"type"=>"setfacl","acl"=>["user:bob:rwx","default:group:dev:r--"],"file"=>"/tmp/testfile.txt"},
541
+ {"type"=>"semanage","context"=>{"user"=>"name","role"=>nil,"type"=>"type","range"=>"s2-s3:c0,c2.c4,c6"},"file"=>"/tmp/testfile.txt"},
542
+ {"type"=>"chown","owner"=>"bob","group"=>"dev","file"=>"/tmp/testfile.txt"}
543
+ ]}.to_json
544
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
545
+ end
546
+
547
+ should "add chown command with just owner" do
548
+ @permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("testfile.txt", {:owner=>"bob"})
549
+ @command_builder = CommandBuilder.new()
550
+ @command_builder.set_permissions("testfile.txt", @permission)
551
+ @expected_json = {"instructions"=>[{"type"=>"chown","owner"=>"bob","group"=>nil,"file"=>"/tmp/testfile.txt"}]}.to_json
552
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
553
+ end
554
+
555
+ should "add chown command with just group" do
556
+ @permission = InstanceAgent::CodeDeployPlugin::ApplicationSpecification::LinuxPermissionInfo.new("testfile.txt", {:group=>"dev"})
557
+ @command_builder = CommandBuilder.new()
558
+ @command_builder.set_permissions("testfile.txt", @permission)
559
+ @expected_json = {"instructions"=>[{"type"=>"chown","owner"=>nil,"group"=>"dev","file"=>"/tmp/testfile.txt"}]}.to_json
560
+ assert_equal JSON.parse(@expected_json), JSON.parse(@command_builder.to_json)
561
+ end
562
+ end
563
+ end
564
+ end
565
+ end
566
+ end