diff --git a/lib/aws/codedeploy/local/cli_validator.rb b/lib/aws/codedeploy/local/cli_validator.rb index 254327c2..ef6e9e84 100644 --- a/lib/aws/codedeploy/local/cli_validator.rb +++ b/lib/aws/codedeploy/local/cli_validator.rb @@ -40,8 +40,12 @@ def validate(args) end if (type == 'directory' && (uri.scheme != 'https' && uri.scheme != 's3' && File.directory?(location))) - unless File.exists? "#{location}/appspec.yml" - raise ValidationError.new("Expecting appspec file at location #{location}/appspec.yml but it is not found there. Please either run the CLI from within a directory containing the appspec.yml file or specify a bundle location containing an appspec.yml file in its root directory") + appspec_filename = args['--appspec-filename'] + if !appspec_filename.nil? && !File.exists?("#{location}/#{appspec_filename}") + raise ValidationError.new("Expecting appspec file at location #{location}/#{appspec_filename} but it is not found there. Please either run the CLI from within a directory containing the #{appspec_filename} file or specify a bundle location containing an #{appspec_filename} file in its root directory") + end + if !File.exists?("#{location}/appspec.yml") && !File.exists?("#{location}/appspec.yaml") + raise ValidationError.new("Expecting appspec file at location #{location}/appspec.yml or #{location}/appspec.yaml but it is not found there. Please either run the CLI from within a directory containing the appspec.yml or appspec.yaml file or specify a bundle location containing an appspec.yml or appspec.yaml file in its root directory") end end @@ -60,7 +64,7 @@ def validate(args) end def any_new_revision_event_or_install_before_download_bundle(events) - events_using_new_revision.push('Install').any? do |event_not_allowed_before_download_bundle| + events_using_new_revision.push('Install').any? do |event_not_allowed_before_download_bundle| events.take_while{|e| e != 'DownloadBundle'}.include? event_not_allowed_before_download_bundle end end diff --git a/lib/aws/codedeploy/local/deployer.rb b/lib/aws/codedeploy/local/deployer.rb index 4e7a2880..58116437 100644 --- a/lib/aws/codedeploy/local/deployer.rb +++ b/lib/aws/codedeploy/local/deployer.rb @@ -76,7 +76,7 @@ def execute_events(args) deployment_group_id = args['--deployment-group'] events = self.class.events_from_comma_separated_list(args['--events']) - spec = build_spec(args['--bundle-location'], args['--type'], deployment_group_id, args['--file-exists-behavior'], all_possible_lifecycle_events(events), args['--deployment-group-name'], args['--application-name']) + spec = build_spec(args['--bundle-location'], args['--type'], deployment_group_id, args['--file-exists-behavior'], all_possible_lifecycle_events(events), args['--deployment-group-name'], args['--application-name'], args['--appspec-filename']) command_executor = InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor.new(:hook_mapping => hook_mapping(events)) all_lifecycle_events_to_execute = add_download_bundle_and_install_events(ordered_lifecycle_events(events)) @@ -126,7 +126,7 @@ def hook_mapping(events) Hash[all_events_plus_default_events_minus_required_events.map{|h|[h,[h]]}] end - def build_spec(location, bundle_type, deployment_group_id, file_exists_behavior, all_possible_lifecycle_events, deployment_group_name, application_name) + def build_spec(location, bundle_type, deployment_group_id, file_exists_behavior, all_possible_lifecycle_events, deployment_group_name, application_name, appspec_filename) @deployment_id = self.class.random_deployment_id puts "Starting to execute deployment from within folder #{deployment_folder(deployment_group_id, @deployment_id)}" OpenStruct.new({ @@ -134,6 +134,7 @@ def build_spec(location, bundle_type, deployment_group_id, file_exists_behavior, :payload => { "ApplicationId" => location, "ApplicationName" => application_name || location, + "AppSpecFilename" => appspec_filename || "appspec.yml", "DeploymentGroupId" => deployment_group_id, "DeploymentGroupName" => deployment_group_name || "LocalFleet", "DeploymentId" => @deployment_id, diff --git a/lib/instance_agent/plugins/codedeploy/command_executor.rb b/lib/instance_agent/plugins/codedeploy/command_executor.rb index 4c3fae2f..9a09a37d 100644 --- a/lib/instance_agent/plugins/codedeploy/command_executor.rb +++ b/lib/instance_agent/plugins/codedeploy/command_executor.rb @@ -156,7 +156,7 @@ def map :deployment_root_dir => deployment_root_dir(deployment_spec), :last_successful_deployment_dir => last_successful_deployment_dir(deployment_spec.deployment_group_id), :most_recent_deployment_dir => most_recent_deployment_dir(deployment_spec.deployment_group_id), - :app_spec_path => app_spec_path) + :app_spec_path => deployment_spec.app_spec_path) script_log.concat_log(hook_command.execute) end script_log.log @@ -185,7 +185,7 @@ def last_successful_deployment_dir(deployment_group) return unless File.exist? last_successful_install_file_location File.open last_successful_install_file_location do |f| return f.read.chomp - end + end end private @@ -194,29 +194,30 @@ def most_recent_deployment_dir(deployment_group) return unless File.exist? most_recent_install_file_location File.open most_recent_install_file_location do |f| return f.read.chomp - end + end end private def default_app_spec(deployment_spec) - default_app_spec_location = File.join(archive_root_dir(deployment_spec), app_spec_path) - log(:debug, "Checking for app spec in #{default_app_spec_location}") - validate_app_spec_hooks(ApplicationSpecification::ApplicationSpecification.parse(File.read(default_app_spec_location)), deployment_spec.all_possible_lifecycle_events) + app_spec_location = app_spec_real_path(deployment_spec) + validate_app_spec_hooks(app_spec_location, deployment_spec.all_possible_lifecycle_events) end private - def validate_app_spec_hooks(app_spec, all_possible_lifecycle_events) + def validate_app_spec_hooks(app_spec_location, all_possible_lifecycle_events) + app_spec = ApplicationSpecification::ApplicationSpecification.parse(File.read(app_spec_location)) + app_spec_filename = File.basename(app_spec_location) unless all_possible_lifecycle_events.nil? app_spec_hooks_plus_hooks_from_mapping = app_spec.hooks.keys.to_set.merge(@hook_mapping.keys).to_a unless app_spec_hooks_plus_hooks_from_mapping.to_set.subset?(all_possible_lifecycle_events.to_set) unknown_lifecycle_events = app_spec_hooks_plus_hooks_from_mapping - all_possible_lifecycle_events - raise ArgumentError.new("appspec.yml file contains unknown lifecycle events: #{unknown_lifecycle_events}") + raise ArgumentError.new("#{app_spec_filename} file contains unknown lifecycle events: #{unknown_lifecycle_events}") end app_spec_hooks_plus_hooks_from_default_mapping = app_spec.hooks.keys.to_set.merge(InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller::DEFAULT_HOOK_MAPPING.keys).to_a custom_hooks_not_found_in_appspec = custom_lifecycle_events(all_possible_lifecycle_events) - app_spec_hooks_plus_hooks_from_default_mapping unless (custom_hooks_not_found_in_appspec).empty? - raise ArgumentError.new("You specified a lifecycle event which is not a default one and doesn't exist in your appspec.yml file: #{custom_hooks_not_found_in_appspec.join(',')}") + raise ArgumentError.new("You specified a lifecycle event which is not a default one and doesn't exist in your #{app_spec_filename} file: #{custom_hooks_not_found_in_appspec.join(',')}") end end @@ -297,7 +298,7 @@ def s3_options proxy_uri = nil if InstanceAgent::Config.config[:proxy_uri] proxy_uri = URI(InstanceAgent::Config.config[:proxy_uri]) - end + end options[:http_proxy] = proxy_uri if InstanceAgent::Config.config[:log_aws_wire] @@ -309,10 +310,10 @@ def s3_options 64 * 1024 * 1024) options[:http_wire_trace] = true end - - options - end - + + options + end + private def download_from_github(deployment_spec, account, repo, commit, anonymous, token) @@ -425,7 +426,7 @@ def unpack_bundle(cmd, bundle_file, deployment_spec) # If the top level of the archive is a directory that contains an appspec, # strip that before giving up - if ((archive_root_files.size == 1) && + if ((archive_root_files.size == 1) && File.directory?(File.join(dst, archive_root_files[0])) && Dir.entries(File.join(dst, archive_root_files[0])).grep(/appspec/i).any?) log(:info, "Stripping leading directory from archive bundle contents.") @@ -440,7 +441,7 @@ def unpack_bundle(cmd, bundle_file, deployment_spec) FileUtils.mv(nested_archive_root, dst) FileUtils.rmdir(tmp_dst) - log(:debug, Dir.entries(dst).join("; ")) + log(:debug, Dir.entries(dst).join("; ")) end end @@ -456,7 +457,7 @@ def update_most_recent_install(deployment_spec) File.open(most_recent_install_file_path(deployment_spec.deployment_group_id), 'w+') do |f| f.write deployment_root_dir(deployment_spec) end - end + end private def cleanup_old_archives(deployment_spec) @@ -468,7 +469,7 @@ def cleanup_old_archives(deployment_spec) full_path_deployment_archives = deployment_archives.map{ |f| File.join(ProcessManager::Config.config[:root_dir], deployment_group, f)} full_path_deployment_archives.delete(deployment_root_dir(deployment_spec)) - + extra = full_path_deployment_archives.size - @archives_to_retain + 1 return unless extra > 0 @@ -481,7 +482,7 @@ def cleanup_old_archives(deployment_spec) # Absolute path takes care of relative root directories directories = oldest_extra.map{ |f| File.absolute_path(f) } - log(:debug,"Delete Files #{directories}" ) + log(:debug, "Delete Files #{directories}") InstanceAgent::Platform.util.delete_dirs_command(directories) end @@ -496,6 +497,24 @@ def app_spec_path 'appspec.yml' end + # Checks for existence the possible extensions of the app_spec_path (.yml and .yaml) + private + def app_spec_real_path(deployment_spec) + app_spec_param_location = File.join(archive_root_dir(deployment_spec), deployment_spec.app_spec_path) + app_spec_yaml_location = File.join(archive_root_dir(deployment_spec), "appspec.yaml") + app_spec_yml_location = File.join(archive_root_dir(deployment_spec), "appspec.yml") + if File.exist? app_spec_param_location + log(:debug, "Using appspec file #{app_spec_param_location}") + app_spec_param_location + elsif File.exist? app_spec_yaml_location + log(:debug, "Using appspec file #{app_spec_yaml_location}") + app_spec_yaml_location + else + log(:debug, "Using appspec file #{app_spec_yml_location}") + app_spec_yml_location + end + end + private def description self.class.to_s diff --git a/lib/instance_agent/plugins/codedeploy/deployment_specification.rb b/lib/instance_agent/plugins/codedeploy/deployment_specification.rb index 689da1ae..664f9662 100644 --- a/lib/instance_agent/plugins/codedeploy/deployment_specification.rb +++ b/lib/instance_agent/plugins/codedeploy/deployment_specification.rb @@ -13,6 +13,7 @@ class DeploymentSpecification attr_accessor :external_account, :repository, :commit_id, :anonymous, :external_auth_token attr_accessor :file_exists_behavior attr_accessor :local_location, :all_possible_lifecycle_events + attr_accessor :app_spec_path class << self attr_accessor :cert_store end @@ -47,6 +48,12 @@ def initialize(data) @deployment_creator = data["DeploymentCreator"] || "user" @deployment_type = data["DeploymentType"] || "IN_PLACE" + if property_set?(data, "AppSpecFilename") + @app_spec_path = data["AppSpecFilename"] + else + @app_spec_path = "appspec.yml" + end + raise 'Must specify a revison' unless data["Revision"] @revision_source = data["Revision"]["RevisionType"] raise 'Must specify a revision source' unless @revision_source @@ -99,7 +106,7 @@ def initialize(data) end # Decrypts the envelope /deployment specs # Params: - # envelope: deployment specification thats to be cheked and decrypted + # envelope: deployment specification that's to be checked and decrypted def self.parse(envelope) raise 'Provided deployment spec was nil' if envelope.nil? diff --git a/spec/aws/codedeploy/local/cli_validator_spec.rb b/spec/aws/codedeploy/local/cli_validator_spec.rb index 8f1b1f00..f3a54e68 100644 --- a/spec/aws/codedeploy/local/cli_validator_spec.rb +++ b/spec/aws/codedeploy/local/cli_validator_spec.rb @@ -86,7 +86,7 @@ end end - context 'when loction is directory but appspec is missing' do + context 'when location is directory but appspec is missing' do let(:args) do {"--bundle-location"=>FAKE_DIRECTORY, "--type"=>'directory'} @@ -96,7 +96,23 @@ allow(File).to receive(:exists?).with(FAKE_DIRECTORY).and_return(true) allow(File).to receive(:directory?).with(FAKE_DIRECTORY).and_return(true) expect(File).to receive(:exists?).with("#{FAKE_DIRECTORY}/appspec.yml").and_return(false) - expect{validator.validate(args)}.to raise_error(AWS::CodeDeploy::Local::CLIValidator::ValidationError, "Expecting appspec file at location #{FAKE_DIRECTORY}/appspec.yml but it is not found there. Please either run the CLI from within a directory containing the appspec.yml file or specify a bundle location containing an appspec.yml file in its root directory") + expect(File).to receive(:exists?).with("#{FAKE_DIRECTORY}/appspec.yaml").and_return(false) + expect{validator.validate(args)}.to raise_error(AWS::CodeDeploy::Local::CLIValidator::ValidationError, "Expecting appspec file at location #{FAKE_DIRECTORY}/appspec.yml or #{FAKE_DIRECTORY}/appspec.yaml but it is not found there. Please either run the CLI from within a directory containing the appspec.yml or appspec.yaml file or specify a bundle location containing an appspec.yml or appspec.yaml file in its root directory") + end + end + + context 'when location is directory and --appspec-filename is specified (but not existing)' do + let(:args) do + {"--bundle-location"=>FAKE_DIRECTORY, + "--type"=>'directory', + "--appspec-filename"=>"appspec-override.yaml"} + end + + it 'throws a ValidationError' do + allow(File).to receive(:exists?).with(FAKE_DIRECTORY).and_return(true) + allow(File).to receive(:directory?).with(FAKE_DIRECTORY).and_return(true) + expect(File).to receive(:exists?).with("#{FAKE_DIRECTORY}/appspec-override.yaml").and_return(false) + expect{validator.validate(args)}.to raise_error(AWS::CodeDeploy::Local::CLIValidator::ValidationError, "Expecting appspec file at location #{FAKE_DIRECTORY}/appspec-override.yaml but it is not found there. Please either run the CLI from within a directory containing the appspec-override.yaml file or specify a bundle location containing an appspec-override.yaml file in its root directory") end end @@ -225,7 +241,7 @@ allow(File).to receive(:directory?).with(FAKE_DIRECTORY).and_return(true) expect(File).to receive(:exists?).with("#{FAKE_DIRECTORY}/appspec.yml").and_return(true) expect(validator.validate(args)).to equal(args) - end + end end end end diff --git a/spec/aws/codedeploy/local/deployer_spec.rb b/spec/aws/codedeploy/local/deployer_spec.rb index 442d829e..bdf11077 100644 --- a/spec/aws/codedeploy/local/deployer_spec.rb +++ b/spec/aws/codedeploy/local/deployer_spec.rb @@ -562,9 +562,71 @@ def create_config_file(working_directory, log_dir = nil) AWS::CodeDeploy::Local::Deployer.new(@config_file_location).execute_events(args) end end + + context 'when appspec-filename is not in the args' do + let(:args) do + {"deploy"=>true, + '--file-exists-behavior'=>InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification::DEFAULT_FILE_EXISTS_BEHAVIOR, + "--location"=>true, + "--bundle-location"=>SAMPLE_FILE_BUNDLE, + "--type"=>'tgz', + '--deployment-group'=>DEPLOYMENT_GROUP_ID, + '--deployment-group-name'=>SAMPLE_DEPLOYMENT_GROUP_NAME, + "--help"=>false, + "--version"=>false} + end + it 'generates a spec with the provided value' do + allow(File).to receive(:exists?).with(SAMPLE_FILE_BUNDLE).and_return(true) + executor = double(InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor) + + expect(InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor).to receive(:new). + with(:hook_mapping => EXPECTED_HOOK_MAPPING). + and_return(executor) + + AWS::CodeDeploy::Local::Deployer::DEFAULT_ORDERED_LIFECYCLE_EVENTS.each do |name| + expect(executor).to receive(:execute_command).with( + OpenStruct.new(:command_name => name), + deployment_spec(SAMPLE_FILE_BUNDLE, 'Local File', 'tgz', + AWS::CodeDeploy::Local::Deployer::DEFAULT_ORDERED_LIFECYCLE_EVENTS, deployment_group_name:SAMPLE_DEPLOYMENT_GROUP_NAME, application_name: nil)).once.ordered + end + AWS::CodeDeploy::Local::Deployer.new(@config_file_location).execute_events(args) + end + end + + context 'when appspec-filename is in the args' do + let(:args) do + {"deploy"=>true, + '--file-exists-behavior'=>InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification::DEFAULT_FILE_EXISTS_BEHAVIOR, + "--location"=>true, + "--appspec-filename"=>"appspec-override.yaml", + "--bundle-location"=>SAMPLE_FILE_BUNDLE, + "--type"=>'tgz', + '--deployment-group'=>DEPLOYMENT_GROUP_ID, + '--deployment-group-name'=>SAMPLE_DEPLOYMENT_GROUP_NAME, + "--help"=>false, + "--version"=>false} + end + it 'generates a spec with the provided value' do + allow(File).to receive(:exists?).with(SAMPLE_FILE_BUNDLE).and_return(true) + executor = double(InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor) + + expect(InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor).to receive(:new). + with(:hook_mapping => EXPECTED_HOOK_MAPPING). + and_return(executor) + + AWS::CodeDeploy::Local::Deployer::DEFAULT_ORDERED_LIFECYCLE_EVENTS.each do |name| + expect(executor).to receive(:execute_command).with( + OpenStruct.new(:command_name => name), + deployment_spec(SAMPLE_FILE_BUNDLE, 'Local File', 'tgz', + AWS::CodeDeploy::Local::Deployer::DEFAULT_ORDERED_LIFECYCLE_EVENTS, deployment_group_name:SAMPLE_DEPLOYMENT_GROUP_NAME, application_name: nil, appspec_filename: "appspec-override.yaml")).once.ordered + end + AWS::CodeDeploy::Local::Deployer.new(@config_file_location).execute_events(args) + end + end + end - def deployment_spec(location, revision_type, bundle_type, all_possible_lifecycle_events, s3revision_includes_version=false, s3revision_includes_etag=false, deployment_group_id=DEPLOYMENT_GROUP_ID, file_exists_behavior=InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification::DEFAULT_FILE_EXISTS_BEHAVIOR, deployment_group_name:nil, application_name:nil) + def deployment_spec(location, revision_type, bundle_type, all_possible_lifecycle_events, s3revision_includes_version=false, s3revision_includes_etag=false, deployment_group_id=DEPLOYMENT_GROUP_ID, file_exists_behavior=InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification::DEFAULT_FILE_EXISTS_BEHAVIOR, deployment_group_name:nil, application_name:nil, appspec_filename: nil) revision_data_key = revision_data(revision_type, location, bundle_type, s3revision_includes_version, s3revision_includes_etag).keys.first revision_data_value = revision_data(revision_type, location, bundle_type, s3revision_includes_version, s3revision_includes_etag).values.first OpenStruct.new({ @@ -572,6 +634,7 @@ def deployment_spec(location, revision_type, bundle_type, all_possible_lifecycle :payload => { "ApplicationId" => location, "ApplicationName" => application_name || location, + "AppSpecFilename" => appspec_filename || "appspec.yml", "DeploymentGroupId" => deployment_group_id, "DeploymentGroupName" => deployment_group_name || "LocalFleet", "DeploymentId" => TEST_DEPLOYMENT_ID, @@ -579,7 +642,6 @@ def deployment_spec(location, revision_type, bundle_type, all_possible_lifecycle "Revision" => {"RevisionType" => revision_type, revision_data_key => revision_data_value}, "AllPossibleLifecycleEvents" => all_possible_lifecycle_events - }.to_json.to_s }) end diff --git a/test/instance_agent/plugins/codedeploy/command_executor_test.rb b/test/instance_agent/plugins/codedeploy/command_executor_test.rb index e1a290f9..bd2ce6e8 100644 --- a/test/instance_agent/plugins/codedeploy/command_executor_test.rb +++ b/test/instance_agent/plugins/codedeploy/command_executor_test.rb @@ -152,10 +152,8 @@ def generate_signed_message_for(map) File.stubs(:open).with(@last_successful_install_file_location) @app_spec = mock("parsed application specification") - File. - stubs(:read). - with("#@archive_root_dir/appspec.yml"). - returns("APP SPEC") + File.stubs(:exist?).with("#@archive_root_dir/appspec.yml").returns(true) + File.stubs(:read).with("#@archive_root_dir/appspec.yml").returns("APP SPEC") ApplicationSpecification::ApplicationSpecification.stubs(:parse).with("APP SPEC").returns(@app_spec) end @@ -238,6 +236,91 @@ def generate_signed_message_for(map) @command_executor.execute_command(@command, deployment_spec) end end + + should 'honor the AppSpecFilename command variable' do + deployment_spec = generate_signed_message_for({ + "DeploymentId" => @deployment_id.to_s, + "DeploymentGroupId" => @deployment_group_id, + "ApplicationName" => @application_name, + "DeploymentGroupName" => @deployment_group_name, + "DeploymentCreator" => @deployment_creator, + "DeploymentType" => @deployment_type, + "AgentActionOverrides" => @agent_actions_overrides, + "AppSpecFilename" => "appspec-override.yaml", + "Revision" => { + "RevisionType" => "S3", + "S3Revision" => @s3Revision + } + }) + + File.expects(:exist?).with("#@archive_root_dir/appspec-override.yaml").returns(true) + File.expects(:read).with("#@archive_root_dir/appspec-override.yaml").returns("APP SPEC") + @command_executor.execute_command(@command, deployment_spec) + end + + should 'fallback to appspec.yaml if provided AppSpecFilename variable points to a file which does\'t exist' do + deployment_spec = generate_signed_message_for({ + "DeploymentId" => @deployment_id.to_s, + "DeploymentGroupId" => @deployment_group_id, + "ApplicationName" => @application_name, + "DeploymentGroupName" => @deployment_group_name, + "DeploymentCreator" => @deployment_creator, + "DeploymentType" => @deployment_type, + "AgentActionOverrides" => @agent_actions_overrides, + "AppSpecFilename" => "appspec-override.yaml", + "Revision" => { + "RevisionType" => "S3", + "S3Revision" => @s3Revision + } + }) + + File.expects(:exist?).with("#@archive_root_dir/appspec-override.yaml").returns(false) + File.expects(:exist?).with("#@archive_root_dir/appspec.yaml").returns(true) + File.expects(:read).with("#@archive_root_dir/appspec.yaml").returns("APP SPEC") + @command_executor.execute_command(@command, deployment_spec) + end + should 'fallback to appspec.yaml if both AppSpecFilename variable and appspec.yaml don\'t exist' do + deployment_spec = generate_signed_message_for({ + "DeploymentId" => @deployment_id.to_s, + "DeploymentGroupId" => @deployment_group_id, + "ApplicationName" => @application_name, + "DeploymentGroupName" => @deployment_group_name, + "DeploymentCreator" => @deployment_creator, + "DeploymentType" => @deployment_type, + "AgentActionOverrides" => @agent_actions_overrides, + "AppSpecFilename" => "appspec-override.yaml", + "Revision" => { + "RevisionType" => "S3", + "S3Revision" => @s3Revision + } + }) + + File.expects(:exist?).with("#@archive_root_dir/appspec-override.yaml").returns(false) + File.expects(:exist?).with("#@archive_root_dir/appspec.yaml").returns(false) + File.expects(:read).with("#@archive_root_dir/appspec.yml").returns("APP SPEC") + @command_executor.execute_command(@command, deployment_spec) + end + + should 'fallback to appspec.yaml if appspec.yml is not there and no AppSpecFilename arg is specified' do + deployment_spec = generate_signed_message_for({ + "DeploymentId" => @deployment_id.to_s, + "DeploymentGroupId" => @deployment_group_id, + "ApplicationName" => @application_name, + "DeploymentGroupName" => @deployment_group_name, + "DeploymentCreator" => @deployment_creator, + "DeploymentType" => @deployment_type, + "AgentActionOverrides" => @agent_actions_overrides, + "Revision" => { + "RevisionType" => "S3", + "S3Revision" => @s3Revision + } + }) + + File.expects(:exist?).with("#@archive_root_dir/appspec.yml").returns(false) + File.expects(:exist?).with("#@archive_root_dir/appspec.yaml").returns(true) + File.expects(:read).with("#@archive_root_dir/appspec.yaml").returns("APP SPEC") + @command_executor.execute_command(@command, deployment_spec) + end end context "when executing the DownloadBundle command" do @@ -322,8 +405,8 @@ def generate_signed_message_for(map) end context "when creating S3 options" do - - should "use right signature version" do + + should "use right signature version" do assert_equal 'v4', @command_executor.s3_options[:signature_version] end @@ -335,7 +418,7 @@ def generate_signed_message_for(map) assert_equal "https://example.override.endpoint.com", @command_executor.s3_options[:endpoint].to_s end end - + context "when no override endpoint provided and not using fips" do setup do InstanceAgent::Config.config[:s3_endpoint_override] = nil @@ -356,9 +439,9 @@ def generate_signed_message_for(map) assert_equal 'us-east-1', @command_executor.s3_options[:region] assert_true @command_executor.s3_options.include? :endpoint end - end + end end - + context "downloading bundle from S3" do setup do File.expects(:open).with(File.join(@deployment_root_dir, 'bundle.tar'), 'wb').yields(@mock_file) @@ -610,7 +693,7 @@ def generate_signed_message_for(map) :deployment_group_id => @deployment_group_id, :deployment_creator => @deployment_creator, :deployment_type => @deployment_type, - :deployment_root_dir => @deployment_root_dir, + :deployment_root_dir => @deployment_root_dir, :last_successful_deployment_dir => nil, :most_recent_deployment_dir => nil, :app_spec_path => 'appspec.yml'} diff --git a/test/instance_agent/plugins/codedeploy/deployment_specification_test.rb b/test/instance_agent/plugins/codedeploy/deployment_specification_test.rb index b3bbc594..2b0c4af1 100644 --- a/test/instance_agent/plugins/codedeploy/deployment_specification_test.rb +++ b/test/instance_agent/plugins/codedeploy/deployment_specification_test.rb @@ -25,7 +25,7 @@ def generate_signed_message_for(map) @agent_actions_overrides = {"AgentOverrides" => @agent_actions_overrides_map} @bundle_type = 'tar' InstanceAgent::Config.init - end + end context 'With Github Revision' do setup do @@ -601,6 +601,22 @@ def generate_signed_message_for(map) end end + context "with app_spec_path" do + should "use the variable set by the AppSpecFilename variable" do + @deployment_spec["AppSpecFilename"] = "foo.yaml" + @packed_message = generate_signed_message_for(@deployment_spec) + parsed_deployment_spec = InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification.parse(@packed_message) + assert_equal "foo.yaml", parsed_deployment_spec.app_spec_path + end + + should "fallback to appspec.yml if AppSpecFilename is not set" do + @deployment_spec.delete("AppSpecFilename") + @packed_message = generate_signed_message_for(@deployment_spec) + parsed_deployment_spec = InstanceAgent::Plugins::CodeDeployPlugin::DeploymentSpecification.parse(@packed_message) + assert_equal "appspec.yml", parsed_deployment_spec.app_spec_path + end + end + context "with file_exists_behavior" do should "set file_exists_behavior to DISALLOW when AgentActionOverrides is not set" do @deployment_spec.delete("AgentActionOverrides")