aws-codedeploy-agent 0.0.1
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.
- data/.gitignore +2 -0
- data/CHANGES.md +3 -0
- data/Gemfile +13 -0
- data/LICENSE +177 -0
- data/NOTICE +2 -0
- data/README.md +16 -0
- data/aws-codedeploy-agent.gemspec +39 -0
- data/bin/codedeploy-agent +78 -0
- data/bin/codedeploy-install +15 -0
- data/bin/codedeploy-uninstall +13 -0
- data/certs/host-agent-deployment-signer-ca-chain.pem +76 -0
- data/conf/codedeployagent.yml +9 -0
- data/init.d/codedeploy-agent +61 -0
- data/lib/core_ext.rb +71 -0
- data/lib/instance_agent.rb +35 -0
- data/lib/instance_agent/agent/base.rb +34 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +133 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +163 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +142 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +23 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +23 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +121 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +66 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +134 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +27 -0
- data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +72 -0
- data/lib/instance_agent/codedeploy_plugin/command_executor.rb +357 -0
- data/lib/instance_agent/codedeploy_plugin/command_poller.rb +146 -0
- data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +150 -0
- data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +206 -0
- data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +374 -0
- data/lib/instance_agent/codedeploy_plugin/installer.rb +143 -0
- data/lib/instance_agent/codedeploy_plugin/request_helper.rb +28 -0
- data/lib/instance_agent/config.rb +43 -0
- data/lib/instance_agent/log.rb +3 -0
- data/lib/instance_agent/platform.rb +17 -0
- data/lib/instance_agent/platform/linux_util.rb +57 -0
- data/lib/instance_agent/runner/child.rb +57 -0
- data/lib/instance_agent/runner/master.rb +103 -0
- data/lib/instance_metadata.rb +47 -0
- data/test/certificate_helper.rb +120 -0
- data/test/helpers/instance_agent_helper.rb +25 -0
- data/test/instance_agent/agent/base_test.rb +49 -0
- data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +1710 -0
- data/test/instance_agent/codedeploy_plugin/codedeploy_control_test.rb +51 -0
- data/test/instance_agent/codedeploy_plugin/command_executor_test.rb +513 -0
- data/test/instance_agent/codedeploy_plugin/command_poller_test.rb +459 -0
- data/test/instance_agent/codedeploy_plugin/deployment_specification_test.rb +335 -0
- data/test/instance_agent/codedeploy_plugin/hook_executor_test.rb +250 -0
- data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +566 -0
- data/test/instance_agent/codedeploy_plugin/installer_test.rb +519 -0
- data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +37 -0
- data/test/instance_agent/config_test.rb +64 -0
- data/test/instance_agent/runner/child_test.rb +87 -0
- data/test/instance_metadata_test.rb +97 -0
- data/test/test_helper.rb +16 -0
- data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -0
- data/vendor/gems/codedeploy-commands/apis/CodeDeployCommand.api.json +372 -0
- data/vendor/gems/codedeploy-commands/codedeploy-commands-1.0.0.gemspec +28 -0
- data/vendor/gems/codedeploy-commands/lib/aws/codedeploy_commands.rb +18 -0
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/certificate_authority.rb +12 -0
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +22 -0
- data/vendor/gems/process_manager/README.md +1 -0
- data/vendor/gems/process_manager/lib/blank.rb +153 -0
- data/vendor/gems/process_manager/lib/core_ext.rb +73 -0
- data/vendor/gems/process_manager/lib/process_manager.rb +49 -0
- data/vendor/gems/process_manager/lib/process_manager/child.rb +119 -0
- data/vendor/gems/process_manager/lib/process_manager/config.rb +112 -0
- data/vendor/gems/process_manager/lib/process_manager/log.rb +107 -0
- data/vendor/gems/process_manager/lib/process_manager/master.rb +322 -0
- data/vendor/gems/process_manager/process_manager-0.0.13.gemspec +42 -0
- data/vendor/specifications/aws-sdk-core-2.0.5.gemspec +39 -0
- data/vendor/specifications/builder-3.2.2.gemspec +29 -0
- data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +28 -0
- data/vendor/specifications/gli-2.5.6.gemspec +51 -0
- data/vendor/specifications/jamespath-0.5.1.gemspec +35 -0
- data/vendor/specifications/little-plugger-1.1.3.gemspec +32 -0
- data/vendor/specifications/logging-1.8.1.gemspec +44 -0
- data/vendor/specifications/multi_json-1.7.7.gemspec +30 -0
- data/vendor/specifications/multi_json-1.8.4.gemspec +30 -0
- data/vendor/specifications/multi_xml-0.5.5.gemspec +30 -0
- data/vendor/specifications/process_manager-0.0.13.gemspec +42 -0
- data/vendor/specifications/simple_pid-0.2.1.gemspec +28 -0
- metadata +377 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'instance_metadata'
|
|
2
|
+
|
|
3
|
+
class CodeDeployControlTest < InstanceAgentTestCase
|
|
4
|
+
|
|
5
|
+
include InstanceAgent::CodeDeployPlugin
|
|
6
|
+
|
|
7
|
+
context "The CodeDeploy interface client" do
|
|
8
|
+
|
|
9
|
+
context "when initializing" do
|
|
10
|
+
setup do
|
|
11
|
+
ENV['AWS_ACCESS_KEY_ID'] = "Test Access Key"
|
|
12
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = "Test Secret Access Key"
|
|
13
|
+
ENV['AWS_REGION'] = nil
|
|
14
|
+
ENV['AWSDEPLOY_CONTROL_ENDPOINT'] = "https://tempuri"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "with region, endpoint and credentials" do
|
|
18
|
+
should "successfully initialize" do
|
|
19
|
+
codedeploy_control_client = CodeDeployControl.new(:region => "us-west-2")
|
|
20
|
+
codedeploy_control_client.get_client
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "without a region" do
|
|
25
|
+
should "raise an exception" do
|
|
26
|
+
assert_raise {
|
|
27
|
+
codedeploy_control_client = CodeDeployControl.new()
|
|
28
|
+
codedeploy_control_client.get_client
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "without an endpoint" do
|
|
34
|
+
setup do
|
|
35
|
+
ENV['AWS_DEPLOY_CONTROL_ENDPOINT'] = nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should "raise an exception" do
|
|
39
|
+
assert_raise {
|
|
40
|
+
codedeploy_control_client = CodeDeployControl.new(:region => "us-west-2")
|
|
41
|
+
codedeploy_control_client.get_client.put_host_command_complete(
|
|
42
|
+
:command_status => 'Succeeded',
|
|
43
|
+
:diagnostics => nil,
|
|
44
|
+
:host_command_identifier => "TestCommand")
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
require 'instance_agent/codedeploy_plugin/installer'
|
|
4
|
+
require 'com/amazon/codedeploy/command/v20141006/host_command_instance'
|
|
5
|
+
require 'aws-sdk-core/s3'
|
|
6
|
+
|
|
7
|
+
class CodeDeployPluginCommandExecutorTest < InstanceAgentTestCase
|
|
8
|
+
|
|
9
|
+
include InstanceAgent::CodeDeployPlugin
|
|
10
|
+
|
|
11
|
+
context 'The CodeDeploy Plugin Command Executor' do
|
|
12
|
+
setup do
|
|
13
|
+
@test_hook_mapping = { "BeforeELBRemove"=>["BeforeELBRemove"],
|
|
14
|
+
"AfterELBRemove"=>["AfterELBRemove"],
|
|
15
|
+
"ApplicationStop"=>["ApplicationStop"],
|
|
16
|
+
"BeforeInstall"=>["BeforeInstall"],
|
|
17
|
+
"AfterInstall"=>["AfterInstall"],
|
|
18
|
+
"ApplicationStart"=>["ApplicationStart"],
|
|
19
|
+
"BeforeELBAdd"=>["BeforeELBAdd"],
|
|
20
|
+
"AfterELBAdd"=>["AfterELBAdd"],
|
|
21
|
+
"ValidateService"=>["ValidateService"]}
|
|
22
|
+
@deploy_control_client = mock
|
|
23
|
+
@command_executor = InstanceAgent::CodeDeployPlugin::CommandExecutor.new({
|
|
24
|
+
:deploy_control_client => @deploy_control_client,
|
|
25
|
+
:hook_mapping => @test_hook_mapping})
|
|
26
|
+
@aws_region = 'us-east-1'
|
|
27
|
+
InstanceMetadata.stubs(:region).returns(@aws_region)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "deployment_system method" do
|
|
31
|
+
should "always return CodeDeploy" do
|
|
32
|
+
assert_equal "CodeDeploy", @command_executor.deployment_system
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "when executing a command" do
|
|
37
|
+
def generate_signed_message_for(map)
|
|
38
|
+
message = @cert_helper.sign_message(map.to_json)
|
|
39
|
+
spec = OpenStruct.new({ :payload => message })
|
|
40
|
+
spec.format = "PKCS7/JSON"
|
|
41
|
+
|
|
42
|
+
return spec
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
setup do
|
|
46
|
+
@cert_helper = CertificateHelper.new
|
|
47
|
+
@deployment_id = SecureRandom.uuid
|
|
48
|
+
@deployment_group_id = "foo"
|
|
49
|
+
@s3Revision = {
|
|
50
|
+
"Bucket" => "mybucket",
|
|
51
|
+
"Key" => "mykey",
|
|
52
|
+
"BundleType" => "tar"
|
|
53
|
+
}
|
|
54
|
+
@deployment_spec = generate_signed_message_for({
|
|
55
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
56
|
+
"DeploymentGroupId" => @deployment_group_id,
|
|
57
|
+
"Revision" => {
|
|
58
|
+
"RevisionType" => "S3",
|
|
59
|
+
"S3Revision" => @s3Revision
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
@command = Com::Amazon::Codedeploy::Command::V20141006::HostCommandInstance.new(
|
|
63
|
+
:host_command_identifier => "command-1",
|
|
64
|
+
:deployment_execution_id => "test-execution")
|
|
65
|
+
@root_dir = '/tmp/codedeploy/'
|
|
66
|
+
@deployment_root_dir = File.join(@root_dir, @deployment_group_id.to_s, @deployment_id.to_s)
|
|
67
|
+
@deployment_instructions_dir = File.join(@root_dir, 'deployment-instructions')
|
|
68
|
+
@archive_root_dir = File.join(@deployment_root_dir, 'deployment-archive')
|
|
69
|
+
ProcessManager::Config.config[:root_dir] = @root_dir
|
|
70
|
+
|
|
71
|
+
FileUtils.stubs(:mkdir_p)
|
|
72
|
+
File.stubs(:directory?).with(@deployment_root_dir).returns(true)
|
|
73
|
+
@previous_install_file_location = File.join(@deployment_instructions_dir, "#{@deployment_group_id}_last_successful_install")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "when executing an unknown command" do
|
|
77
|
+
setup do
|
|
78
|
+
@command.command_name = "unknown-command"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
should "not create the deployment root directory" do
|
|
82
|
+
# Need to unstub the :mkdir_p method otherwise the never expectation doesn't work
|
|
83
|
+
FileUtils.unstub(:mkdir_p)
|
|
84
|
+
FileUtils.expects(:mkdir_p).never
|
|
85
|
+
|
|
86
|
+
assert_raised_with_message('Unsupported command type: unknown-command.', InstanceAgent::CodeDeployPlugin::CommandExecutor::InvalidCommandNameFailure) do
|
|
87
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
should "throw an exception" do
|
|
92
|
+
assert_raised_with_message('Unsupported command type: unknown-command.', InstanceAgent::CodeDeployPlugin::CommandExecutor::InvalidCommandNameFailure) do
|
|
93
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context "when executing a valid command" do
|
|
99
|
+
setup do
|
|
100
|
+
@command.command_name = "Install"
|
|
101
|
+
@command_executor.stubs(:install)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
should "create the deployment root directory" do
|
|
105
|
+
FileUtils.expects(:mkdir_p).with(@deployment_root_dir)
|
|
106
|
+
|
|
107
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "when failed to create root directory" do
|
|
111
|
+
setup do
|
|
112
|
+
File.stubs(:directory?).with(@deployment_root_dir).returns(false)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
should "raise an exception" do
|
|
116
|
+
assert_raised_with_message("Error creating deployment root directory #{@deployment_root_dir}") do
|
|
117
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context "when executing the Install command" do
|
|
124
|
+
|
|
125
|
+
setup do
|
|
126
|
+
@command.command_name = "Install"
|
|
127
|
+
InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ApplicationSpecification.stubs(:parse).returns(@app_spec)
|
|
128
|
+
@installer = stub("installer", :install => nil)
|
|
129
|
+
Installer.stubs(:new).returns(@installer)
|
|
130
|
+
File.stubs(:exist?).with(@previous_install_file_location).returns(true)
|
|
131
|
+
File.stubs(:exist?).with(@archive_root_dir).returns(true)
|
|
132
|
+
File.stubs(:open).with(@previous_install_file_location, 'w+')
|
|
133
|
+
File.stubs(:open).with(@previous_install_file_location)
|
|
134
|
+
|
|
135
|
+
@app_spec = mock("parsed application specification")
|
|
136
|
+
File.
|
|
137
|
+
stubs(:read).
|
|
138
|
+
with("#@archive_root_dir/appspec.yml").
|
|
139
|
+
returns("APP SPEC")
|
|
140
|
+
ApplicationSpecification::ApplicationSpecification.stubs(:parse).with("APP SPEC").returns(@app_spec)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
should "idempotently create the instructions directory" do
|
|
144
|
+
FileUtils.expects(:mkdir_p).with(@deployment_instructions_dir)
|
|
145
|
+
|
|
146
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
should "create an appropriate Installer" do
|
|
150
|
+
Installer.
|
|
151
|
+
expects(:new).
|
|
152
|
+
with(:deployment_instructions_dir => @deployment_instructions_dir,
|
|
153
|
+
:deployment_archive_dir => @archive_root_dir).
|
|
154
|
+
returns(@installer)
|
|
155
|
+
|
|
156
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
should "perform the installation for the current IG, revision and app spec" do
|
|
160
|
+
@installer.expects(:install).with(@deployment_group_id, @app_spec)
|
|
161
|
+
|
|
162
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
should "write the archive root dir to the install instructions file" do
|
|
166
|
+
mock_file = mock
|
|
167
|
+
File.expects(:open).with(@previous_install_file_location, 'w+').yields(mock_file)
|
|
168
|
+
mock_file.expects(:write).with(@deployment_root_dir)
|
|
169
|
+
|
|
170
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "when executing the DownloadBundle command" do
|
|
176
|
+
setup do
|
|
177
|
+
InstanceAgent::LinuxUtil.stubs(:extract_tar)
|
|
178
|
+
InstanceAgent::LinuxUtil.stubs(:extract_tgz)
|
|
179
|
+
@command.command_name = "DownloadBundle"
|
|
180
|
+
@http = mock
|
|
181
|
+
@mock_file = mock
|
|
182
|
+
Net::HTTP.stubs(:start).yields(@http)
|
|
183
|
+
File.stubs(:open).returns @mock_file
|
|
184
|
+
@mock_file.stubs(:close)
|
|
185
|
+
@http.stubs(:request_get)
|
|
186
|
+
@s3 = mock
|
|
187
|
+
Aws::S3::Client.stubs(:new).returns(@s3)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context "downloading bundle from S3" do
|
|
191
|
+
setup do
|
|
192
|
+
File.expects(:open).with(File.join(@deployment_root_dir, 'bundle.tar'), 'wb').yields(@mock_file)
|
|
193
|
+
@object = mock
|
|
194
|
+
@s3.stubs(:get_object).returns(@object)
|
|
195
|
+
@io = mock
|
|
196
|
+
@object.stubs(:etag).returns("myetag")
|
|
197
|
+
@deployment_spec = generate_signed_message_for({
|
|
198
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
199
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
200
|
+
"Revision" => {
|
|
201
|
+
"RevisionType" => "S3",
|
|
202
|
+
"S3Revision" => {
|
|
203
|
+
"Bucket" => "mybucket",
|
|
204
|
+
"Key" => "mykey",
|
|
205
|
+
"BundleType" => "tar"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
context "when setting up the S3 client" do
|
|
212
|
+
setup do
|
|
213
|
+
ENV['AWS_REGION'] = nil
|
|
214
|
+
InstanceMetadata.stubs(:region).returns('us-east-1')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
should "read from the InstanceMetadata to get the region" do
|
|
218
|
+
InstanceMetadata.expects(:region)
|
|
219
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
should "verify etag" do
|
|
224
|
+
@deployment_spec = generate_signed_message_for({
|
|
225
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
226
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
227
|
+
"Revision" => {
|
|
228
|
+
"RevisionType" => "S3",
|
|
229
|
+
"S3Revision" => {
|
|
230
|
+
"Bucket" => "mybucket",
|
|
231
|
+
"Key" => "mykey",
|
|
232
|
+
"BundleType" => "tar",
|
|
233
|
+
"ETag" => "myetag"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
should "verify etag that contains quotations still matches" do
|
|
241
|
+
@object.stubs(:etag).returns("\"myetag\"")
|
|
242
|
+
@deployment_spec = generate_signed_message_for({
|
|
243
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
244
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
245
|
+
"Revision" => {
|
|
246
|
+
"RevisionType" => "S3",
|
|
247
|
+
"S3Revision" => {
|
|
248
|
+
"Bucket" => "mybucket",
|
|
249
|
+
"Key" => "mykey",
|
|
250
|
+
"BundleType" => "tar",
|
|
251
|
+
"ETag" => "myetag"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
should "verify version" do
|
|
259
|
+
@object.stubs(:body).with(:bucket => "mybucket", :key => "mykey", :version_id => "myversion").returns(@io)
|
|
260
|
+
@deployment_spec = generate_signed_message_for({
|
|
261
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
262
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
263
|
+
"Revision" => {
|
|
264
|
+
"RevisionType" => "S3",
|
|
265
|
+
"S3Revision" => {
|
|
266
|
+
"Bucket" => "mybucket",
|
|
267
|
+
"Key" => "mykey",
|
|
268
|
+
"BundleType" => "tar",
|
|
269
|
+
"Version" => "myversion"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
should "call zip for zip BundleTypes" do
|
|
277
|
+
@deployment_spec = generate_signed_message_for({
|
|
278
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
279
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
280
|
+
"Revision" => {
|
|
281
|
+
"RevisionType" => "S3",
|
|
282
|
+
"S3Revision" => {
|
|
283
|
+
"Bucket" => "mybucket",
|
|
284
|
+
"Key" => "mykey",
|
|
285
|
+
"BundleType" => "zip"
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
Zip::File.expects(:open).with(File.join(@deployment_root_dir, 'bundle.tar'))
|
|
290
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
should "call extract_tgz for Gzipped tar BundleTypes" do
|
|
294
|
+
@deployment_spec = generate_signed_message_for({
|
|
295
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
296
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
297
|
+
"Revision" => {
|
|
298
|
+
"RevisionType" => "S3",
|
|
299
|
+
"S3Revision" => {
|
|
300
|
+
"Bucket" => "mybucket",
|
|
301
|
+
"Key" => "mykey",
|
|
302
|
+
"BundleType" => "tgz"
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
InstanceAgent::LinuxUtil.expects(:extract_tgz).with(File.join(@deployment_root_dir, 'bundle.tar'), @archive_root_dir)
|
|
307
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
should "call extract_tar for tar BundleTypes" do
|
|
311
|
+
@deployment_spec = generate_signed_message_for({
|
|
312
|
+
"DeploymentId" => @deployment_id.to_s,
|
|
313
|
+
"DeploymentGroupId" => @deployment_group_id.to_s,
|
|
314
|
+
"Revision" => {
|
|
315
|
+
"RevisionType" => "S3",
|
|
316
|
+
"S3Revision" => {
|
|
317
|
+
"Bucket" => "mybucket",
|
|
318
|
+
"Key" => "mykey",
|
|
319
|
+
"BundleType" => "tar"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
InstanceAgent::LinuxUtil.expects(:extract_tar).with(File.join(@deployment_root_dir, 'bundle.tar'), @archive_root_dir)
|
|
324
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
should "unpack the bundle to the right directory" do
|
|
330
|
+
InstanceAgent::LinuxUtil.expects(:extract_tar).with(File.join(@deployment_root_dir, 'bundle.tar'), @archive_root_dir)
|
|
331
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
should "remove the directory before unpacking" do
|
|
335
|
+
call_sequence = sequence("call sequence")
|
|
336
|
+
FileUtils.expects(:rm_rf).with(@archive_root_dir).in_sequence(call_sequence)
|
|
337
|
+
InstanceAgent::LinuxUtil.expects(:extract_tar).in_sequence(call_sequence)
|
|
338
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
context "I have an empty app spec (for script mapping)" do
|
|
343
|
+
setup do
|
|
344
|
+
File.stubs(:read).with(File.join(@archive_root_dir, 'appspec.yml')).returns(nil)
|
|
345
|
+
InstanceAgent::CodeDeployPlugin::ApplicationSpecification::ApplicationSpecification.stubs(:parse).returns(nil)
|
|
346
|
+
@hook_executor_constructor_hash = {
|
|
347
|
+
:deployment_root_dir => @deployment_root_dir,
|
|
348
|
+
:last_successful_deployment_dir => nil,
|
|
349
|
+
:app_spec_path => 'appspec.yml'}
|
|
350
|
+
@mock_hook_executor = mock
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
context "BeforeELBRemove" do
|
|
354
|
+
setup do
|
|
355
|
+
@command.command_name = "BeforeELBRemove"
|
|
356
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "BeforeELBRemove"
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
should "call execute a hook executor object with BeforeELBRemove as one of the params" do
|
|
360
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
361
|
+
@mock_hook_executor.expects(:execute)
|
|
362
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
context "AfterELBRemove" do
|
|
367
|
+
setup do
|
|
368
|
+
@command.command_name = "AfterELBRemove"
|
|
369
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "AfterELBRemove"
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
should "call execute a hook executor object with AfterELBRemove as one of the params" do
|
|
373
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
374
|
+
@mock_hook_executor.expects(:execute)
|
|
375
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
context "ApplicationStop" do
|
|
380
|
+
setup do
|
|
381
|
+
@command.command_name = "ApplicationStop"
|
|
382
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "ApplicationStop"
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
should "call execute a hook executor object with ApplicationStop as one of the params" do
|
|
386
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
387
|
+
@mock_hook_executor.expects(:execute)
|
|
388
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
context "BeforeInstall" do
|
|
393
|
+
setup do
|
|
394
|
+
@command.command_name = "BeforeInstall"
|
|
395
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "BeforeInstall"
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
should "call execute a hook executor object with BeforeInstall as one of the params" do
|
|
399
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
400
|
+
@mock_hook_executor.expects(:execute)
|
|
401
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
context "AfterInstall" do
|
|
406
|
+
setup do
|
|
407
|
+
@command.command_name = "AfterInstall"
|
|
408
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "AfterInstall"
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
should "call execute a hook executor object with AfterInstall as one of the params" do
|
|
412
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
413
|
+
@mock_hook_executor.expects(:execute)
|
|
414
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
context "ApplicationStart" do
|
|
419
|
+
setup do
|
|
420
|
+
@command.command_name = "ApplicationStart"
|
|
421
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "ApplicationStart"
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
should "call execute a hook executor object with ApplicationStart as one of the params" do
|
|
425
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
426
|
+
@mock_hook_executor.expects(:execute)
|
|
427
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
context "BeforeELBAdd" do
|
|
432
|
+
setup do
|
|
433
|
+
@command.command_name = "BeforeELBAdd"
|
|
434
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "BeforeELBAdd"
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
should "call execute a hook executor object with BeforeELBAdd as one of the params" do
|
|
438
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
439
|
+
@mock_hook_executor.expects(:execute)
|
|
440
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
context "AfterELBAdd" do
|
|
445
|
+
setup do
|
|
446
|
+
@command.command_name = "AfterELBAdd"
|
|
447
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "AfterELBAdd"
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
should "call execute a hook executor object with AfterELBAdd as one of the params" do
|
|
451
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
452
|
+
@mock_hook_executor.expects(:execute)
|
|
453
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
context "ValidateService" do
|
|
458
|
+
setup do
|
|
459
|
+
@command.command_name = "ValidateService"
|
|
460
|
+
@hook_executor_constructor_hash[:lifecycle_event] = "ValidateService"
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
should "call execute a hook executor object with ValidateService as one of the params" do
|
|
464
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash).returns(@mock_hook_executor)
|
|
465
|
+
@mock_hook_executor.expects(:execute)
|
|
466
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
#non 1:1 mapping tests
|
|
472
|
+
context "one command hooks to multiple lifecycle events" do
|
|
473
|
+
setup do
|
|
474
|
+
@command.command_name = "test_command"
|
|
475
|
+
@test_hook_mapping = { "test_command" => ["lifecycle_event_1","lifecycle_event_2"]}
|
|
476
|
+
@deploy_control_client = mock
|
|
477
|
+
@command_executor = InstanceAgent::CodeDeployPlugin::CommandExecutor.new({
|
|
478
|
+
:deploy_control_client => @deploy_control_client,
|
|
479
|
+
:hook_mapping => @test_hook_mapping})
|
|
480
|
+
hook_executor_constructor_hash = {
|
|
481
|
+
:deployment_root_dir => @deployment_root_dir,
|
|
482
|
+
:last_successful_deployment_dir => nil,
|
|
483
|
+
:app_spec_path => 'appspec.yml'}
|
|
484
|
+
@hook_executor_constructor_hash_1 = hook_executor_constructor_hash.merge({:lifecycle_event => "lifecycle_event_1"})
|
|
485
|
+
@hook_executor_constructor_hash_2 = hook_executor_constructor_hash.merge({:lifecycle_event => "lifecycle_event_2"})
|
|
486
|
+
@mock_hook_executor = mock
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
should "call both lifecycle events" do
|
|
490
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash_1).returns(@mock_hook_executor)
|
|
491
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash_2).returns(@mock_hook_executor)
|
|
492
|
+
@mock_hook_executor.expects(:execute).twice
|
|
493
|
+
|
|
494
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
context "when the first script is forced to fail" do
|
|
498
|
+
setup do
|
|
499
|
+
HookExecutor.stubs(:new).with(@hook_executor_constructor_hash_1).raises("failed to create hook caommand")
|
|
500
|
+
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
should "calls lifecycle event 1 and fails but not 2" do
|
|
504
|
+
assert_raised_with_message('failed to create hook caommand') do
|
|
505
|
+
@command_executor.execute_command(@command, @deployment_spec)
|
|
506
|
+
end
|
|
507
|
+
HookExecutor.expects(:new).with(@hook_executor_constructor_hash_2).never
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
end
|