diff --git a/Gemfile b/Gemfile index 8fce5259..f463de01 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,7 @@ group :test do gem 'coveralls_reborn', require: false gem 'cucumber' gem 'fakefs', :require => 'fakefs/safe' - gem 'mocha' + gem 'mocha', "0.13.3" gem 'rspec' gem 'webmock', :require => 'webmock/rspec' gem 'shoulda' diff --git a/codedeploy_agent.gemspec b/codedeploy_agent.gemspec index de08e7d0..6b3e81bd 100644 --- a/codedeploy_agent.gemspec +++ b/codedeploy_agent.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = 'aws_codedeploy_agent' - spec.version = '1.4.0' + spec.version = '1.4.1' spec.summary = 'Packages AWS CodeDeploy agent libraries' spec.description = 'AWS CodeDeploy agent is responsible for doing the actual work of deploying software on an individual EC2 instance' spec.author = 'Amazon Web Services' diff --git a/lib/instance_agent/plugins/codedeploy/command_executor.rb b/lib/instance_agent/plugins/codedeploy/command_executor.rb index 6ab2d86c..8910cc75 100644 --- a/lib/instance_agent/plugins/codedeploy/command_executor.rb +++ b/lib/instance_agent/plugins/codedeploy/command_executor.rb @@ -304,8 +304,6 @@ def download_from_s3(deployment_spec, bucket, key, version, etag) log(:info, "Downloading artifact bundle from bucket '#{bucket}' and key '#{key}', version '#{version}', etag '#{etag}'") options = s3_options() s3 = Aws::S3::Client.new(options) - ProcessManager::Log.info("s3 client configuration below:") - ProcessManager::Log.info(s3.config) File.open(artifact_bundle(deployment_spec), 'wb') do |file| @@ -346,10 +344,10 @@ def s3_options options[:region] = region if !InstanceAgent::Config.config[:s3_endpoint_override].to_s.empty? - ProcessManager::Log.info("using s3 override endpoint #{InstanceAgent::Config.config[:s3_endpoint_override]}") + ProcessManager::Log.debug("using s3 override endpoint #{InstanceAgent::Config.config[:s3_endpoint_override]}") options[:endpoint] = URI(InstanceAgent::Config.config[:s3_endpoint_override]) elsif InstanceAgent::Config.config[:use_fips_mode] - ProcessManager::Log.info("using fips endpoint") + ProcessManager::Log.debug("using fips endpoint") # There was a recent change to S3 client to decompose the region and use a FIPS endpoint is "fips-" is appended # to the region. However, this is such a recent change that we cannot rely on the latest version of the SDK to be loaded. # For now, the endpoint will be set directly if FIPS is active but can switch to the S3 method once we have broader support. diff --git a/lib/instance_agent/plugins/codedeploy/command_poller.rb b/lib/instance_agent/plugins/codedeploy/command_poller.rb index 4b7a3049..101915fd 100644 --- a/lib/instance_agent/plugins/codedeploy/command_poller.rb +++ b/lib/instance_agent/plugins/codedeploy/command_poller.rb @@ -143,7 +143,12 @@ def process_command(command, spec) private def next_command log(:debug, "Calling PollHostCommand:") - output = @deploy_control_client.poll_host_command(:host_identifier => @host_identifier) + begin + output = @deploy_control_client.poll_host_command(:host_identifier => @host_identifier) + rescue Exception => e + log(:error, "Error polling for host commands: #{e.class} - #{e.message} - #{e.backtrace.join("\n")}") + raise e + end command = output.host_command if command.nil? log(:debug, "PollHostCommand: Host Command = nil") diff --git a/vendor/gems/codedeploy-commands-1.0.0/apis/ApolloDeployControlService_mock.api.json b/vendor/gems/codedeploy-commands-1.0.0/apis/ApolloDeployControlService_mock.api.json new file mode 100644 index 00000000..f3177263 --- /dev/null +++ b/vendor/gems/codedeploy-commands-1.0.0/apis/ApolloDeployControlService_mock.api.json @@ -0,0 +1,369 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2014-10-06", + "endpointPrefix": "codedeploy-commands", + "jsonVersion": "1.1", + "serviceAbbreviation": "CodeDeployCommand", + "serviceFullName": "AWS CodeDeploy Command Service", + "signatureVersion": "v4", + "targetPrefix": "ApolloDeployControlService_mock", + "protocol": "json" + }, + "documentation": "Control plane for the CodeDeploy stack. Exposes APIs needed by CodeDeploy clients to run deployment commands.", + "operations": { + "GetDeploymentSpecification": { + "name": "GetDeploymentSpecification", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "GetDeploymentSpecificationInput" + }, + "output": { + "shape": "GetDeploymentSpecificationOutput" + }, + "errors": [ + { + "shape": "ClientException", + "exception": true, + "documentation": "This exception indicates that the request failed due to the fault of the customer (either an invalid request was provided, referred to a non-existant object, or another reason within the client's control)." + }, + { + "shape": "ServerException", + "exception": true, + "fault": true, + "documentation": "This exception indicates that the request failed due to a problem on the server, or with the server's dependencies." + } + ], + "documentation": "Retrieve the deployment specification for the deployment and host, consisting of the client metadata provided when the deployment was created. The generic client metadata will be provided, as well as the client metadata for the host's variant (if variant-specific metadata was provided). Throws DeploymentNotFoundException if the DeploymentExecutionId does not identify a current deployment. Throws HostNotFoundException if the host is not recognized by the deployment engine. Throws ServerException for failures caused by the deployment system or its dependencies." + }, + "PollHostCommand": { + "name": "PollHostCommand", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "PollHostCommandInput" + }, + "output": { + "shape": "PollHostCommandOutput" + }, + "errors": [ + { + "shape": "ClientException", + "exception": true, + "documentation": "This exception indicates that the request failed due to the fault of the customer (either an invalid request was provided, referred to a non-existant object, or another reason within the client's control)." + }, + { + "shape": "ServerException", + "exception": true, + "fault": true, + "documentation": "This exception indicates that the request failed due to a problem on the server, or with the server's dependencies." + } + ], + "documentation": "This requests a command from the deployment workflow engine. If no command is ready to be dispatched, the output will be empty (HostCommand will be null). Throws HostNotFoundException if the host is not recognized by the deployment engine. Throws ServerException for failures caused by the deployment system or its dependencies." + }, + "PostHostCommandUpdate": { + "name": "PostHostCommandUpdate", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "PostHostCommandUpdateInput" + }, + "output": { + "shape": "PostHostCommandUpdateOutput" + }, + "errors": [ + { + "shape": "ClientException", + "exception": true, + "documentation": "This exception indicates that the request failed due to the fault of the customer (either an invalid request was provided, referred to a non-existant object, or another reason within the client's control)." + }, + { + "shape": "ServerException", + "exception": true, + "fault": true, + "documentation": "This exception indicates that the request failed due to a problem on the server, or with the server's dependencies." + } + ], + "documentation": "This updates the central workflow engine with the current progress of the host command. This will also return the status of the host command centrally if possible, so agents can skip processing the command if it has been aborted / timed out. However, the status is optional, so if no status is returned the agent should treat it as if it was ok to continue. Throws ClientException for an invalid HostCommandIdentifier or Diagnostics. Throws ServerException for failures caused by the deployment system or its dependencies." + }, + "PutHostCommandAcknowledgement": { + "name": "PutHostCommandAcknowledgement", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "PutHostCommandAcknowledgementInput" + }, + "output": { + "shape": "PutHostCommandAcknowledgementOutput" + }, + "errors": [ + { + "shape": "ClientException", + "exception": true, + "documentation": "This exception indicates that the request failed due to the fault of the customer (either an invalid request was provided, referred to a non-existant object, or another reason within the client's control)." + }, + { + "shape": "ServerException", + "exception": true, + "fault": true, + "documentation": "This exception indicates that the request failed due to a problem on the server, or with the server's dependencies." + } + ], + "documentation": "This notifies the central workflow engine that the agent has received the specified command and is ready to start execution. This will also return the status of the host command centrally if possible, so agents can skip processing the command if it has been aborted / timed out. However, the status is optional, so if no status is returned the agent should treat it as if it was ok to continue. Throws ClientException for an invalid HostCommandIdentifier or Diagnostics. Throws ServerException for failures caused by the deployment system or its dependencies." + }, + "PutHostCommandComplete": { + "name": "PutHostCommandComplete", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "PutHostCommandCompleteInput" + }, + "errors": [ + { + "shape": "ClientException", + "exception": true, + "documentation": "This exception indicates that the request failed due to the fault of the customer (either an invalid request was provided, referred to a non-existant object, or another reason within the client's control)." + }, + { + "shape": "ServerException", + "exception": true, + "fault": true, + "documentation": "This exception indicates that the request failed due to a problem on the server, or with the server's dependencies." + } + ], + "documentation": "This reports completion of the command back to the workflow engine. Throws ClientException for an invalid HostCommandIdentifier or Diagnostics. Throws ServerException for failures caused by the deployment system or its dependencies." + } + }, + "shapes": { + "ClientException": { + "type": "structure", + "members": { + }, + "exception": true, + "documentation": "This exception indicates that the request failed due to the fault of the customer (either an invalid request was provided, referred to a non-existant object, or another reason within the client's control)." + }, + "DeploymentCommandName": { + "type": "string" + }, + "DeploymentCommandStatus": { + "type": "string", + "enum": [ + "Pending", + "InProgress", + "Succeeded", + "Failed" + ] + }, + "DeploymentExecutionId": { + "type": "string", + "min": 1, + "max": 129, + "pattern": "^[^/]+/[^/]+/[^/]+/.+$" + }, + "DeploymentSpecification": { + "type": "structure", + "members": { + "GenericEnvelope": { + "shape": "Envelope" + }, + "VariantId": { + "shape": "VariantId" + }, + "VariantEnvelope": { + "shape": "Envelope" + } + }, + "documentation": "The DeploymentSpecification contains an envelope for the generic client metadata, and if there is variant-specific metadata, the ID of the variant for the host and the envelope containing that variant's metadata. All fields are optional, though an empty DeploymentSpecification is likely indicative of an error." + }, + "Envelope": { + "type": "structure", + "members": { + "Format": { + "shape": "Format" + }, + "Payload": { + "shape": "Payload" + } + }, + "documentation": "For an Envelope used for host command diagnostics, Format is limited to 64 characters and Payload is limited to 8192 characters." + }, + "Format": { + "type": "string", + "min": 1, + "max": 64 + }, + "GenericDateTimestamp": { + "type": "timestamp" + }, + "GenericLong": { + "type": "long" + }, + "GenericString": { + "type": "string" + }, + "GetDeploymentSpecificationInput": { + "type": "structure", + "required": [ + "DeploymentExecutionId", + "HostIdentifier" + ], + "members": { + "DeploymentExecutionId": { + "shape": "DeploymentExecutionId" + }, + "HostIdentifier": { + "shape": "HostIdentifier" + } + } + }, + "GetDeploymentSpecificationOutput": { + "type": "structure", + "members": { + "DeploymentSystem": { + "shape": "GenericString" + }, + "DeploymentSpecification": { + "shape": "DeploymentSpecification" + } + } + }, + "HostCommandIdentifier": { + "type": "string" + }, + "HostCommandInstance": { + "type": "structure", + "members": { + "HostCommandIdentifier": { + "shape": "HostCommandIdentifier" + }, + "HostIdentifier": { + "shape": "HostIdentifier" + }, + "DeploymentExecutionId": { + "shape": "DeploymentExecutionId" + }, + "CommandName": { + "shape": "DeploymentCommandName" + }, + "Nonce": { + "shape": "GenericLong" + } + } + }, + "HostIdentifier": { + "type": "string", + "documentation": "An identifier for referring to a unit of capacity." + }, + "Payload": { + "type": "string", + "min": 0, + "max": 8192 + }, + "PollHostCommandInput": { + "type": "structure", + "required": [ + "HostIdentifier" + ], + "members": { + "HostIdentifier": { + "shape": "HostIdentifier" + } + } + }, + "PollHostCommandOutput": { + "type": "structure", + "members": { + "HostCommand": { + "shape": "HostCommandInstance" + } + } + }, + "PostHostCommandUpdateInput": { + "type": "structure", + "required": [ + "HostCommandIdentifier" + ], + "members": { + "HostCommandIdentifier": { + "shape": "HostCommandIdentifier" + }, + "EstimatedCompletionTime": { + "shape": "GenericDateTimestamp" + }, + "Diagnostics": { + "shape": "Envelope" + } + } + }, + "PostHostCommandUpdateOutput": { + "type": "structure", + "members": { + "CommandStatus": { + "shape": "DeploymentCommandStatus" + } + } + }, + "PutHostCommandAcknowledgementInput": { + "type": "structure", + "required": [ + "HostCommandIdentifier" + ], + "members": { + "HostCommandIdentifier": { + "shape": "HostCommandIdentifier" + }, + "Diagnostics": { + "shape": "Envelope" + } + } + }, + "PutHostCommandAcknowledgementOutput": { + "type": "structure", + "members": { + "CommandStatus": { + "shape": "DeploymentCommandStatus" + } + } + }, + "PutHostCommandCompleteInput": { + "type": "structure", + "required": [ + "HostCommandIdentifier", + "CommandStatus" + ], + "members": { + "HostCommandIdentifier": { + "shape": "HostCommandIdentifier" + }, + "CommandStatus": { + "shape": "DeploymentCommandStatus" + }, + "Diagnostics": { + "shape": "Envelope" + } + } + }, + "ServerException": { + "type": "structure", + "members": { + }, + "exception": true, + "fault": true, + "documentation": "This exception indicates that the request failed due to a problem on the server, or with the server's dependencies." + }, + "VariantId": { + "type": "string" + } + } +} diff --git a/vendor/gems/codedeploy-commands-1.0.0/lib/aws/codedeploy_commands.rb b/vendor/gems/codedeploy-commands-1.0.0/lib/aws/codedeploy_commands.rb index 600800b8..0e8e2a13 100644 --- a/vendor/gems/codedeploy-commands-1.0.0/lib/aws/codedeploy_commands.rb +++ b/vendor/gems/codedeploy-commands-1.0.0/lib/aws/codedeploy_commands.rb @@ -7,11 +7,16 @@ require "#{gem_root}/lib/aws/plugins/deploy_agent_version" version = '1.0.0' +SERVICE_CLASS_NAME = 'CodeDeployCommand' if InstanceAgent::Config.config[:enable_auth_policy] bundled_apis = Dir.glob(File.join(gem_root, 'apis', 'CodeDeployCommandSecure.api.json')).group_by do |path| File.basename(path).split('.').first end +elsif InstanceAgent::Config.config[:use_mock_command_service] + bundled_apis = Dir.glob(File.join(gem_root, 'apis', 'ApolloDeployControlService_mock.api.json')).group_by do |path| + File.basename(path).split('.').first + end else bundled_apis = Dir.glob(File.join(gem_root, 'apis', 'CodeDeployCommand.api.json')).group_by do |path| File.basename(path).split('.').first @@ -19,8 +24,7 @@ end bundled_apis.each do |svc_class_name, api_versions| - svc_class_name = "CodeDeployCommand" if svc_class_name.eql?("CodeDeployCommandSecure") - svc_class = Aws.add_service(svc_class_name, api: JSON.parse(File.read(api_versions.first), max_nesting: false)) + svc_class = Aws.add_service(SERVICE_CLASS_NAME, api: JSON.parse(File.read(api_versions.first), max_nesting: false)) svc_class.const_set(:VERSION, version) Aws::CodeDeployCommand::Client.add_plugin(Aws::Plugins::CertificateAuthority) Aws::CodeDeployCommand::Client.add_plugin(Aws::Plugins::DeployControlEndpoint)