diff --git a/lib/dpl/providers/codedeploy.rb b/lib/dpl/providers/codedeploy.rb
index a31955533..65b04c8d7 100644
--- a/lib/dpl/providers/codedeploy.rb
+++ b/lib/dpl/providers/codedeploy.rb
@@ -11,7 +11,8 @@ class Codedeploy < Provider
tbd
str
- gem 'aws-sdk', '~> 2.0'
+ gem 'aws-sdk-codedeploy', '~> 1.0'
+ gem 'aws-sdk-s3', '~> 1.0'
env :aws
config '~/.aws/credentials', '~/.aws/config', prefix: 'aws'
diff --git a/lib/dpl/providers/elasticbeanstalk.rb b/lib/dpl/providers/elasticbeanstalk.rb
index 90e20e036..36b77fd34 100644
--- a/lib/dpl/providers/elasticbeanstalk.rb
+++ b/lib/dpl/providers/elasticbeanstalk.rb
@@ -9,7 +9,8 @@ class Elasticbeanstalk < Provider
tbd
str
- gem 'aws-sdk', '~> 2.0'
+ gem 'aws-sdk-elasticbeanstalk', '~> 1.0'
+ gem 'aws-sdk-s3', '~> 1.0'
gem 'rubyzip', '~> 1.2.2', require: 'zip'
gem 'pathspec', '~> 0.2.1', require: 'pathspec'
@@ -126,8 +127,8 @@ def wait_until_deployed
def check_deployment(msgs)
sleep 5
events.each do |event|
- msg = "#{event[:event_date]} [#{event[:severity]}] #{event[:message]}"
- error "Deployment failed: #{msg}" if event[:severity] == 'ERROR'
+ msg = "#{event.event_date} [#{event.severity}] #{event.message}"
+ error "Deployment failed: #{msg}" if event.severity == 'ERROR'
info msg unless msgs.include?(msg)
msgs << msg
end
diff --git a/lib/dpl/providers/lambda.rb b/lib/dpl/providers/lambda.rb
index fa0f248e8..fc8a63e9e 100644
--- a/lib/dpl/providers/lambda.rb
+++ b/lib/dpl/providers/lambda.rb
@@ -11,7 +11,7 @@ class Lambda < Provider
tbd
str
- gem 'aws-sdk', '~> 2.0'
+ gem 'aws-sdk-lambda', '~> 1.0'
gem 'rubyzip', '~> 1.2.2', require: 'zip'
env :aws
diff --git a/lib/dpl/providers/opsworks.rb b/lib/dpl/providers/opsworks.rb
index 8e2f30655..a3d9ec75b 100644
--- a/lib/dpl/providers/opsworks.rb
+++ b/lib/dpl/providers/opsworks.rb
@@ -9,7 +9,7 @@ class Opsworks < Provider
tbd
str
- gem 'aws-sdk', '~> 2.0'
+ gem 'aws-sdk-opsworks', '~> 1.0'
env :aws
config '~/.aws/credentials', '~/.aws/config', prefix: 'aws'
diff --git a/lib/dpl/providers/s3.rb b/lib/dpl/providers/s3.rb
index 2f90e07f9..695519458 100644
--- a/lib/dpl/providers/s3.rb
+++ b/lib/dpl/providers/s3.rb
@@ -14,7 +14,7 @@ class S3 < Provider
tbd
str
- gem 'aws-sdk', '~> 2.0', require: ['aws-sdk', 'dpl/support/aws_sdk_patch']
+ gem 'aws-sdk-s3', '~> 1.0'
gem 'mime-types', '~> 3.2.2'
env :aws
@@ -57,7 +57,7 @@ class S3 < Provider
def setup
@cwd = Dir.pwd
Dir.chdir(local_dir)
- Aws.eager_autoload!(services: ['S3'])
+ # Aws.eager_autoload!(services: ['S3'])
end
def login
diff --git a/spec/dpl/providers/codedeploy_spec.rb b/spec/dpl/providers/codedeploy_spec.rb
index 7404fdac8..bef66f36d 100644
--- a/spec/dpl/providers/codedeploy_spec.rb
+++ b/spec/dpl/providers/codedeploy_spec.rb
@@ -1,43 +1,31 @@
describe Dpl::Providers::Codedeploy do
- let(:args) { |e| %w(--access_key_id access_key_id --secret_access_key secret_access_key --application app) + args_from_description(e) }
- let(:requests) { Hash.new { |hash, key| hash[key] = [] } }
+ include Support::Matchers::Aws
- env TRAVIS_BUILD_NUMBER: 1
+ let(:args) { |e| %w(--access_key_id access_key_id --secret_access_key secret_access_key --application app) + args_from_description(e) }
+ let(:client) { Aws::CodeDeploy::Client.new(stub_responses: responses[:eb]) }
+ let(:s3) { Aws::S3::Client.new(stub_responses: true) }
- before do
- Aws.config[:s3] = {
- stub_responses: {
- get_object: ->(ctx) {
- requests[:buckets] << ctx.http_request
- { deployment_id: 'deployment_id' }
- }
- }
- }
- Aws.config[:codedeploy] = {
- stub_responses: {
- create_deployment: ->(ctx) {
- requests[:create_deployment] << ctx.http_request
- { deployment_id: 'deployment_id' }
+ let(:responses) do
+ {
+ eb: {
+ create_deployment: {
+ deployment_id: 'deployment_id'
},
- get_deployment: ->(ctx) {
- requests[:get_deployment] << ctx.http_request
- { deployment_info: { status: 'Succeeded' } }
+ get_deployment: {
+ deployment_info: { status: 'Succeeded' }
}
}
}
end
- matcher :create_deployment do |params = {}|
- match do |*|
- next false unless request = requests[:create_deployment][0]
- body = symbolize(JSON.parse(request.body.read))
- params.all? { |key, value| body[key] == value }
- end
- end
+ let(:github_revision) { { revisionType: 'GitHub', gitHubLocation: { repository: 'dpl', commitId: 'sha' } } }
+ let(:s3_revision) { { revisionType: 'S3', s3Location: { bucket: 'bucket', bundleType: 'zip', version: 'ObjectVersionId', eTag: 'ETag' } } }
- matcher :get_deployment do |*|
- match { |*| requests[:get_deployment].any? }
- end
+ env TRAVIS_BUILD_NUMBER: 1
+
+ before { allow(Aws::CodeDeploy::Client).to receive(:new).and_return(client) }
+ before { allow(Aws::S3::Client).to receive(:new).and_return(s3) }
+ before { |c| subject.run unless c.example_group.metadata[:run].is_a?(FalseClass) }
let(:github_revision) { { revisionType: 'GitHub', gitHubLocation: { repository: 'dpl', commitId: 'sha' } } }
let(:s3_revision) { { revisionType: 'S3', s3Location: { bucket: 'bucket', bundleType: 'zip', version: 'ObjectVersionId', eTag: 'ETag' } } }
diff --git a/spec/dpl/providers/elasticbeanstalk_spec.rb b/spec/dpl/providers/elasticbeanstalk_spec.rb
index 0d6b292ee..458bbebd0 100644
--- a/spec/dpl/providers/elasticbeanstalk_spec.rb
+++ b/spec/dpl/providers/elasticbeanstalk_spec.rb
@@ -1,74 +1,56 @@
describe Dpl::Providers::Elasticbeanstalk do
+ include Support::Matchers::Aws
+
let(:args) { |e| required + args_from_description(e) }
let(:required) { %w(--access_key_id id --secret_access_key key --env env --bucket bucket) }
- let(:requests) { Hash.new { |hash, key| hash[key] = [] } }
let(:events) { [] }
- matcher :create_app_version do |opts = {}|
- match do |*|
- next false unless requests[:create_application_version].any?
- next true unless opts[:with]
- body = requests[:create_application_version][0].body.read
- opts[:with].is_a?(Regexp) ? body =~ opts[:with] : body.include?(opts[:with])
- end
- end
-
- matcher :update_environment do
- match do
- requests[:update_environment].any?
- end
- end
+ let(:client) { Aws::ElasticBeanstalk::Client.new(stub_responses: responses) }
+ let(:s3) { Aws::S3::Client.new(stub_responses: true) }
+ let(:events) { [] }
- before do
- Aws.config[:s3] = {
- stub_responses: {
- }
- }
- Aws.config[:elasticbeanstalk] = {
- stub_responses: {
- create_application_version: ->(ctx) {
- requests[:create_application_version] << ctx.http_request
- {
- application_version: {
- version_label: 'label'
- }
- }
- },
- update_environment: ->(ctx) {
- requests[:update_environment] << ctx.http_request
- },
- describe_environments: {
- environments: [
- status: 'Ready'
- ]
- },
- describe_events: {
- events: events
+ let(:responses) do
+ {
+ create_application_version: {
+ application_version: {
+ version_label: 'label'
}
+ },
+ update_environment: {
+ },
+ describe_environments: {
+ environments: [
+ status: 'Ready'
+ ]
+ },
+ describe_events: {
+ events: events
}
}
end
- after { Aws.config.clear }
-
file 'one'
file 'two'
+ before { allow(Aws::ElasticBeanstalk::Client).to receive(:new).and_return(client) }
+ before { allow(Aws::S3::Client).to receive(:new).and_return(s3) }
+ before { |c| subject.run unless c.example_group.metadata[:run].is_a?(FalseClass) }
+
describe 'by default' do
before { subject.run }
it { should have_zipped "travis-sha-#{now.to_i}.zip", %w(one two) }
it { should have_run '[info] Using Access Key: i*******************' }
- it { should create_app_version with: 'ApplicationName=dpl' }
- it { should create_app_version with: 'Description=commit%20msg' }
- it { should create_app_version with: 'S3Bucket=bucket' }
- it { should create_app_version with: /S3Key=travis-sha-.*.zip/ }
- it { should create_app_version with: /VersionLabel=travis-sha.*/ }
+ it { should create_app_version 'ApplicationName=dpl' }
+ it { should create_app_version 'Description=commit%20msg' }
+ it { should create_app_version 'S3Bucket=bucket' }
+ it { should create_app_version /S3Key=travis-sha-.*.zip/ }
+ it { should create_app_version /VersionLabel=travis-sha.*/ }
it { should update_environment }
end
describe 'given --bucket_path one/two' do
before { subject.run }
- it { should create_app_version with: /S3Key=one%2Ftwo%2Ftravis-sha-.*.zip/ }
+ it { should create_app_version /S3Key=one%2Ftwo%2Ftravis-sha-.*.zip/ }
end
describe 'given --only_create_app_version' do
@@ -80,21 +62,21 @@
describe 'given --zip_file other.zip' do
before { subject.run }
it { expect(File.exist?('other.zip')).to be true }
- it { should create_app_version with: /S3Key=travis-sha-.*.zip/ }
+ it { should create_app_version /S3Key=travis-sha-.*.zip/ }
end
- describe 'given --wait_until_deployed' do
+ describe 'given --wait_until_deployed', run: false do
let(:events) { [event_date: Time.now, severity: 'ERROR', message: 'msg'] }
it { expect { subject.run }.to raise_error /Deployment failed/ }
end
- describe 'with an .ebignore file' do
+ describe 'with an .ebignore file', run: false do
file '.ebignore', "*\n!one"
before { subject.run }
it { should have_zipped "travis-sha-#{now.to_i}.zip", %w(one) }
end
- describe 'with ~/.aws/credentials' do
+ describe 'with ~/.aws/credentials', run: false do
let(:args) { |e| %w(--env env --bucket_name bucket) }
file '~/.aws/credentials', <<-str.sub(/^\s*/, '')
@@ -107,7 +89,7 @@
it { should have_run '[info] Using Access Key: ac******************' }
end
- describe 'with ~/.aws/config' do
+ describe 'with ~/.aws/config', run: false do
let(:args) { |e| %w(--access_key_id id --secret_access_key secret) }
file '~/.aws/config', <<-str.sub(/^\s*/, '')
@@ -117,6 +99,6 @@
str
before { subject.run }
- it { should create_app_version with: 'S3Bucket=bucket' }
+ it { should create_app_version 'S3Bucket=bucket' }
end
end
diff --git a/spec/dpl/providers/lambda_spec.rb b/spec/dpl/providers/lambda_spec.rb
index 3fd51ec7d..1217c2710 100644
--- a/spec/dpl/providers/lambda_spec.rb
+++ b/spec/dpl/providers/lambda_spec.rb
@@ -1,44 +1,22 @@
describe Dpl::Providers::Lambda do
- let(:args) { |e| required + args_from_description(e) }
- let(:requests) { Hash.new { |hash, key| hash[key] = [] } }
- let(:exists) { false }
-
- matcher :have_called do |key, params = {}|
- match do |*|
- @body = symbolize(JSON.parse(requests[key][0].body.read)) if requests[key].any?
- @body ? expect(@body).to(include params) : false
- end
-
- failure_message do
- "Expected it to have called #{key.inspect}\n\n #{params.inspect}\n\nbut it was not. Instead it was called with:\n\n #{@body}"
- end
- end
-
- before do
- Aws.config[:lambda] = {
- stub_responses: {
- get_function: ->(ctx) {
- requests[:get_function] << ctx.http_request
- exists ? {} : raise(Aws::Lambda::Errors::ResourceNotFoundException.new(ctx, 'error'))
- },
- create_function: ->(ctx) {
- requests[:create_function] << ctx.http_request
- },
- update_function_configuration: ->(ctx) {
- requests[:update_function_config] << ctx.http_request
- { function_arn: 'arn' }
- },
- update_function_code: ->(ctx) {
- requests[:update_function_code] << ctx.http_request
- },
- tag_resource: ->(ctx) {
- requests[:tag_resource] << ctx.http_request
- }
- }
+ include Support::Matchers::Aws
+
+ let(:args) { |e| required + args_from_description(e) }
+ let(:client) { Aws::Lambda::Client.new(stub_responses: responses) }
+
+ let(:responses) do
+ {
+ get_function: ->(c) {
+ exists ? {} : raise(Aws::Lambda::Errors::ResourceNotFoundException.new(c, 'error'))
+ },
+ create_function: {},
+ update_function_configuration: { function_arn: 'arn' },
+ update_function_code: {},
+ tag_resource: {}
}
end
- after { Aws.config.clear }
+ before { allow(Aws::Lambda::Client).to receive(:new).and_return(client) }
file 'one'
@@ -55,67 +33,67 @@
it { should have_run '[info] Creating function func.' }
it { should have_run_in_order }
- it { should have_called :create_function, FunctionName: 'func' }
- it { should have_called :create_function, Runtime: 'nodejs8.10' }
- it { should have_called :create_function, Code: { ZipFile: instance_of(String) } }
- it { should have_called :create_function, Description: 'Deploy build 1 to AWS Lambda via Travis CI' }
- it { should have_called :create_function, Handler: 'index.handler' }
- it { should have_called :create_function, Role: 'role' }
- it { should have_called :create_function, Timeout: 3 }
- it { should have_called :create_function, MemorySize: 128 }
- it { should have_called :create_function, TracingConfig: { Mode: 'PassThrough' } }
+ it { should create_function FunctionName: 'func' }
+ it { should create_function Runtime: 'nodejs8.10' }
+ it { should create_function Code: { ZipFile: instance_of(String) } }
+ it { should create_function Description: 'Deploy build 1 to AWS Lambda via Travis CI' }
+ it { should create_function Handler: 'index.handler' }
+ it { should create_function Role: 'role' }
+ it { should create_function Timeout: 3 }
+ it { should create_function MemorySize: 128 }
+ it { should create_function TracingConfig: { Mode: 'PassThrough' } }
end
describe 'given --module_name other --handler handler' do
- it { should have_called :create_function, Handler: 'other.handler' }
+ it { should create_function Handler: 'other.handler' }
end
describe 'given --description other' do
- it { should have_called :create_function, Description: 'other' }
+ it { should create_function Description: 'other' }
end
describe 'given --timeout 1' do
- it { should have_called :create_function, Timeout: 1 }
+ it { should create_function Timeout: 1 }
end
describe 'given --memory_size 64' do
- it { should have_called :create_function, MemorySize: 64 }
+ it { should create_function MemorySize: 64 }
end
describe 'given --runtime python2.7' do
- it { should have_called :create_function, Runtime: 'python2.7' }
+ it { should create_function Runtime: 'python2.7' }
end
describe 'given --runtime java8' do
- it { should have_called :create_function, Handler: 'index::handler' }
+ it { should create_function Handler: 'index::handler' }
end
describe 'given --subnet_ids one --subnet_ids two' do
- it { should have_called :create_function, VpcConfig: { SubnetIds: ['one', 'two'] } }
+ it { should create_function VpcConfig: { SubnetIds: ['one', 'two'] } }
end
describe 'given --security_group_ids one --security_group_ids two' do
- it { should have_called :create_function, VpcConfig: { SecurityGroupIds: ['one', 'two'] } }
+ it { should create_function VpcConfig: { SecurityGroupIds: ['one', 'two'] } }
end
describe 'given --dead_letter_arn arn' do
- it { should have_called :create_function, DeadLetterConfig: { TargetArn: 'arn' } }
+ it { should create_function DeadLetterConfig: { TargetArn: 'arn' } }
end
describe 'given --tracing_mode Active' do
- it { should have_called :create_function, TracingConfig: { Mode: 'Active' } }
+ it { should create_function TracingConfig: { Mode: 'Active' } }
end
describe 'given --environment_variables ONE=one --environment_variables TWO=two' do
- it { should have_called :create_function, Environment: { Variables: { ONE: 'one', TWO: 'two' } } }
+ it { should create_function Environment: { Variables: { ONE: 'one', TWO: 'two' } } }
end
describe 'given --kms_key_arn arn' do
- it { should have_called :create_function, KMSKeyArn: 'arn' }
+ it { should create_function KMSKeyArn: 'arn' }
end
describe 'given --function_tags key=value' do
- it { should have_called :create_function, Tags: { key: 'value' } }
+ it { should create_function Tags: { key: 'value' } }
end
end
@@ -130,76 +108,76 @@
it { should have_run '[info] Updating existing function func.' }
it { should have_run '[info] Updating code.' }
- it { should have_called :update_function_config, Runtime: 'nodejs8.10' }
- it { should have_called :update_function_config, Description: 'Deploy build 1 to AWS Lambda via Travis CI' }
- it { should have_called :update_function_config, Timeout: 3 }
- it { should have_called :update_function_config, MemorySize: 128 }
- it { should have_called :update_function_config, TracingConfig: { Mode: 'PassThrough' } }
- it { should have_called :update_function_code, ZipFile: kind_of(String), Publish: false }
+ it { should update_function_config Runtime: 'nodejs8.10' }
+ it { should update_function_config Description: 'Deploy build 1 to AWS Lambda via Travis CI' }
+ it { should update_function_config Timeout: 3 }
+ it { should update_function_config MemorySize: 128 }
+ it { should update_function_config TracingConfig: { Mode: 'PassThrough' } }
+ it { should update_function_code ZipFile: instance_of(String), Publish: false }
end
describe 'given --role role' do
- it { should have_called :update_function_config, Role: 'role' }
+ it { should update_function_config Role: 'role' }
end
describe 'given --handler_name handler' do
- it { should have_called :update_function_config, Handler: 'index.handler' }
+ it { should update_function_config Handler: 'index.handler' }
end
describe 'given --module_name other --handler_name handler' do
- it { should have_called :update_function_config, Handler: 'other.handler' }
+ it { should update_function_config Handler: 'other.handler' }
end
describe 'given --description other' do
- it { should have_called :update_function_config, Description: 'other' }
+ it { should update_function_config Description: 'other' }
end
describe 'given --timeout 1' do
- it { should have_called :update_function_config, Timeout: 1 }
+ it { should update_function_config Timeout: 1 }
end
describe 'given --memory_size 64' do
- it { should have_called :update_function_config, MemorySize: 64 }
+ it { should update_function_config MemorySize: 64 }
end
describe 'given --runtime python2.7' do
- it { should have_called :update_function_config, Runtime: 'python2.7' }
+ it { should update_function_config Runtime: 'python2.7' }
end
describe 'given --subnet_ids one --subnet_ids two' do
- it { should have_called :update_function_config, VpcConfig: { SubnetIds: ['one', 'two'] } }
+ it { should update_function_config VpcConfig: { SubnetIds: ['one', 'two'] } }
end
describe 'given --security_group_ids one --security_group_ids two' do
- it { should have_called :update_function_config, VpcConfig: { SecurityGroupIds: ['one', 'two'] } }
+ it { should update_function_config VpcConfig: { SecurityGroupIds: ['one', 'two'] } }
end
describe 'given --dead_letter_arn arn' do
- it { should have_called :update_function_config, DeadLetterConfig: { TargetArn: 'arn' } }
+ it { should update_function_config DeadLetterConfig: { TargetArn: 'arn' } }
end
describe 'given --tracing_mode Active' do
- it { should have_called :update_function_config, TracingConfig: { Mode: 'Active' } }
+ it { should update_function_config TracingConfig: { Mode: 'Active' } }
end
describe 'given --environment_variables ONE=one --environment_variables TWO=two' do
- it { should have_called :update_function_config, Environment: { Variables: { ONE: 'one', TWO: 'two' } } }
+ it { should update_function_config Environment: { Variables: { ONE: 'one', TWO: 'two' } } }
end
describe 'given --kms_key_arn arn' do
- it { should have_called :update_function_config, KMSKeyArn: 'arn' }
+ it { should update_function_config KMSKeyArn: 'arn' }
end
describe 'given --publish' do
- it { should have_called :update_function_code, Publish: true }
+ it { should update_function_code Publish: true }
end
describe 'given --function_tags key=value' do
- it { should have_called :tag_resource, Tags: { key: 'value' } }
+ it { should tag_resource Tags: { key: 'value' } }
end
describe 'given --layers one --layers two' do
- it { should have_called :update_function_config, Layers: %w(one two) }
+ it { should update_function_config Layers: %w(one two) }
end
end
@@ -219,6 +197,7 @@
describe 'with ~/.aws/config' do
let(:args) { |e| %w(--access_key_id id --secret_access_key secret) }
+ let(:exists) { false }
file '~/.aws/config', <<-str.sub(/^\s*/, '')
[default]
@@ -228,8 +207,8 @@
str
before { subject.run }
- it { should have_called :create_function, FunctionName: 'func' }
- it { should have_called :create_function, Role: 'role' }
- it { should have_called :create_function, Handler: 'index.handler' }
+ it { should create_function FunctionName: 'func' }
+ it { should create_function Role: 'role' }
+ it { should create_function Handler: 'index.handler' }
end
end
diff --git a/spec/dpl/providers/opsworks_spec.rb b/spec/dpl/providers/opsworks_spec.rb
index 781945fcd..f75db1e6e 100644
--- a/spec/dpl/providers/opsworks_spec.rb
+++ b/spec/dpl/providers/opsworks_spec.rb
@@ -1,92 +1,70 @@
describe Dpl::Providers::Opsworks do
- let(:args) { |e| %w(--access_key_id access_key_id --secret_access_key secret_access_key --app_id app) + args_from_description(e) }
- let(:requests) { Hash.new { |hash, key| hash[key] = [] } }
-
- matcher :have_called do |key, params = {}|
- match do |*|
- @body = symbolize(JSON.parse(requests[key][0].body.read)) if requests[key].any?
- @body ? expect(@body).to(include(params)) : false
- end
-
- failure_message do
- "Expected it to have called #{key.inspect}\n\n #{params.inspect}\n\nbut it was not. Instead it was called with:\n\n #{@body}"
- end
- end
-
- before do
- Aws.config[:opsworks] = {
- stub_responses: {
- describe_apps: ->(ctx) {
- requests[:describe_apps] << ctx.http_request
- { apps: [stack_id: 'stack_id', shortname: 'dpl'] }
- },
- create_deployment: ->(ctx) {
- requests[:create_deployment] << ctx.http_request
- { deployment_id: 'id' }
- },
- describe_deployments: ->(ctx) {
- requests[:describe_deployments] << ctx.http_request
- { deployments: [status: 'successful'] }
- },
- update_app: ->(ctx) {
- requests[:update_app] << ctx.http_request
- }
+ include Support::Matchers::Aws
+
+ let(:args) { |e| %w(--access_key_id access_key_id --secret_access_key secret_access_key --app_id app) + args_from_description(e) }
+ let(:client) { Aws::OpsWorks::Client.new(stub_responses: responses) }
+
+ let(:responses) do
+ {
+ describe_apps: {
+ apps: [stack_id: 'stack_id', shortname: 'dpl']
+ },
+ create_deployment: {
+ deployment_id: 'id'
+ },
+ describe_deployments: {
+ deployments: [status: 'successful']
+ },
+ update_app: {
}
}
end
- after { Aws.config.clear }
+ before { allow(Aws::OpsWorks::Client).to receive(:new).and_return(client) }
+ before { |c| subject.run unless c.example_group.metadata[:run].is_a?(FalseClass) }
- context do
- before { subject.run }
+ describe 'by default', record: true do
+ let(:json) { JSON.dump(deploy: { dpl: { migrate: false, scm: { revision: 'sha' } } }) }
+
+ it { should have_run '[info] Using Access Key: ac******************' }
+ it { should have_run '[print] Creating deployment ... ' }
+ it { should have_run '[info] Done: id' }
+ it { should have_run_in_order }
+
+ it { should create_deployment StackId: 'stack_id' }
+ it { should create_deployment AppId: 'app' }
+ it { should create_deployment Command: { Name: 'deploy' } }
+ it { should create_deployment Comment: 'Deploy build 1 via Travis CI' }
+ it { should create_deployment CustomJson: json }
+ end
+
+ describe 'given --instance_ids one --instance_ids two' do
+ it { should create_deployment InstanceIds: ['one', 'two'] }
+ end
+
+ describe 'given --layer_ids one --layer_ids two' do
+ it { should create_deployment LayerIds: ['one', 'two'] }
+ end
+
+ describe 'given --migrate' do
+ let(:json) { JSON.dump(deploy: { dpl: { migrate: true, scm: { revision: 'sha' } } }) }
+ it { should create_deployment CustomJson: json }
+ end
+
+ describe 'given --custom_json danger:will-robinson' do
+ it { should create_deployment CustomJson: 'danger:will-robinson' }
+ end
+
+ describe 'given --wait_until_deployed' do
+ it { should have_run '[print] Deploying ' }
+ it { should describe_deployments DeploymentIds: ['id'] }
+ end
- describe 'by default', record: true do
- let(:json) { JSON.dump(deploy: { dpl: { migrate: false, scm: { revision: 'sha' } } }) }
-
- it { should have_run '[info] Using Access Key: ac******************' }
- it { should have_run '[print] Creating deployment ... ' }
- it { should have_run '[info] Done: id' }
- it { should have_run_in_order }
-
- it do
- should have_called :create_deployment, {
- StackId: 'stack_id',
- AppId: 'app',
- Command: { Name: 'deploy' },
- Comment: 'Deploy build 1 via Travis CI',
- CustomJson: json
- }
- end
- end
-
- describe 'given --instance_ids one --instance_ids two' do
- it { should have_called :create_deployment, InstanceIds: ['one', 'two'] }
- end
-
- describe 'given --layer_ids one --layer_ids two' do
- it { should have_called :create_deployment, LayerIds: ['one', 'two'] }
- end
-
- describe 'given --migrate' do
- let(:json) { JSON.dump(deploy: { dpl: { migrate: true, scm: { revision: 'sha' } } }) }
- it { should have_called :create_deployment, CustomJson: json }
- end
-
- describe 'given --custom_json danger:will-robinson' do
- it { should have_called :create_deployment, CustomJson: 'danger:will-robinson' }
- end
-
- describe 'given --wait_until_deployed' do
- it { should have_run '[print] Deploying ' }
- it { should have_called :describe_deployments, DeploymentIds: ['id'] }
- end
-
- describe 'given --wait_until_deployed --update_on_success' do
- it { should have_called :update_app, AppId: 'app', AppSource: { Revision: 'sha' } }
- end
+ describe 'given --wait_until_deployed --update_on_success' do
+ it { should update_app AppId: 'app', AppSource: { Revision: 'sha' } }
end
- describe 'with ~/.aws/credentials' do
+ describe 'with ~/.aws/credentials', run: false do
let(:args) { |e| %w(--app_id app) }
let(:exists) { false }
@@ -100,7 +78,7 @@
it { should have_run '[info] Using Access Key: ac******************' }
end
- describe 'with ~/.aws/config' do
+ describe 'with ~/.aws/config', run: false do
let(:args) { |e| %w(--access_key_id id --secret_access_key secret) }
file '~/.aws/config', <<-str.sub(/^\s*/, '')
@@ -109,6 +87,6 @@
str
before { subject.run }
- it { should have_called :create_deployment, AppId: 'app' }
+ it { should create_deployment AppId: 'app' }
end
end
diff --git a/spec/dpl/providers/s3_spec.rb b/spec/dpl/providers/s3_spec.rb
index 449c1589e..fb7479e64 100644
--- a/spec/dpl/providers/s3_spec.rb
+++ b/spec/dpl/providers/s3_spec.rb
@@ -1,59 +1,31 @@
describe Dpl::Providers::S3 do
- let(:args) { |e| %w(--access_key_id access_key_id --secret_access_key secret_access_key --bucket bucket) + args_from_description(e) }
- let(:requests) { Hash.new { |hash, key| hash[key] = [] } }
+ include Support::Matchers::Aws
+
+ let(:args) { |e| %w(--access_key_id access_key_id --secret_access_key secret_access_key --bucket bucket) + args_from_description(e) }
+ let(:client) { Aws::S3::Client.new(stub_responses: {}) }
file 'one.txt'
file '.hidden.txt'
- before do
- Aws.config[:s3] = {
- stub_responses: {
- put_object: ->(ctx) {
- requests[:put_object] << ctx.http_request
- },
- put_bucket_website: ->(ctx) {
- requests[:put_bucket_website] << ctx.http_request
- }
- }
- }
- end
-
- matcher :put_object do |file, opts = {}|
- match do |*|
- next false unless request = requests[:put_object].detect { |f| f.body.path == file }
- path = opts.delete(:path)
- return false if path && path != request.endpoint.path
- host = opts.delete(:host)
- return false if host && host != request.endpoint.host
- headers = symbolize(request.headers.to_h)
- expect(headers).to(include(opts)) if headers.any?
- true
- end
- end
-
- matcher :put_bucket_website_suffix do |suffix|
- match do |*|
- next false unless request = requests[:put_bucket_website][0]
- request.body.read.include?("#{suffix}")
- end
- end
-
- before { |c| subject.run unless c.metadata[:run].is_a?(FalseClass) }
+ before { allow(Aws::S3::Client).to receive(:new).and_return(client) }
+ before { |c| subject.run unless c.example_group.metadata[:run].is_a?(FalseClass) }
describe 'by default', record: true do
it { should have_run '[info] Using Access Key: ac******************' }
it { should have_run '[info] Uploading 1 files with up to 5 threads ...' }
it { should have_run '[print] .' }
it { should have_run_in_order }
- it { should put_object 'one.txt', host: 'bucket.s3.amazonaws.com', 'x-amz-acl': 'private', 'cache-control': 'no-cache', 'x-amz-storage-class': 'STANDARD' }
+ # for whatever reason host would either include `us-stubbed-1` or not
+ # depending if this spec is run as part of the full suite or alone.
+ it { should put_object 'one.txt', host: /bucket\.s3\.(us-stubbed-1\.)?amazonaws.com/, 'x-amz-acl': 'private', 'cache-control': 'no-cache', 'x-amz-storage-class': 'STANDARD' }
end
describe 'given --endpoint https://host.com' do
- it { should put_object 'one.txt', host: 'bucket.host.com' }
+ it { should create_client endpoint: URI.parse('https://host.com') }
end
describe 'given --region us-west-1' do
- it { should put_object 'one.txt', host: 'bucket.s3.us-west-1.amazonaws.com' }
+ it { should create_client region: 'us-west-1' }
end
describe 'given --upload_dir dir' do
@@ -61,50 +33,47 @@
end
describe 'given --dot_match' do
+ it { should have_run %r(.hidden.txt) }
it { should put_object '.hidden.txt' }
end
describe 'given --storage_class STANDARD_IA' do
+ it { should have_run %r(one.txt.* storage_class=STANDARD_IA) }
it { should put_object 'one.txt', 'x-amz-storage-class': 'STANDARD_IA' }
end
describe 'given --acl public_read' do
+ it { should have_run %r(one.txt.* acl=public-read) }
it { should put_object 'one.txt', 'x-amz-acl': 'public-read' }
end
describe 'given --cache_control public' do
+ it { should have_run %r(one.txt.* cache_control=public) }
it { should put_object 'one.txt', 'cache-control': 'public' }
end
describe 'given --cache_control max-age=60' do
+ it { should have_run %r(one.txt.* cache_control=max-age=60) }
it { should put_object 'one.txt', 'cache-control': 'max-age=60' }
end
- describe 'given --cache_control "public: *.js" --cache_control "no-cache: *.txt"' do
- it { should put_object 'one.txt', 'cache-control': 'no-cache' }
- end
-
- describe 'given --cache_control "public: *.js" --cache_control "private"' do
- it { should put_object 'one.txt', 'cache-control': 'private' }
- end
-
describe 'given --expires "2020-01-01 00:00:00 UTC"' do
- it { should put_object 'one.txt', 'expires': 'Wed, 01 Jan 2020 00:00:00 GMT' }
- end
-
- describe 'given --expires "2020-01-01 00:00:00 UTC: *.txt, *.js"' do
+ it { should have_run %r(one.txt.* expires=2020-01-01 00:00:00 UTC) }
it { should put_object 'one.txt', 'expires': 'Wed, 01 Jan 2020 00:00:00 GMT' }
end
describe 'given --default_text_charset utf-8' do
+ it { should have_run %r(one.txt.* content_type=text/plain; charset=utf-8) }
it { should put_object 'one.txt', 'content-type': 'text/plain; charset=utf-8' }
end
describe 'given --server_side_encryption' do
+ it { should have_run %r(one.txt.* server_side_encryption=AES256) }
it { should put_object 'one.txt', 'x-amz-server-side-encryption': 'AES256' }
end
describe 'given --detect_encoding' do
+ it { should have_run %r(one.txt.* content_encoding=text) }
it { should put_object 'one.txt', 'content-encoding': 'text' }
end
@@ -150,12 +119,13 @@
file '~/.aws/config', <<-str.sub(/^\s*/, '')
[default]
- region=us-west-1
+ region=us-other-1
bucket=other
str
before { subject.run }
- it { should put_object 'one.txt', host: 'other.s3.us-west-1.amazonaws.com' }
+ it { should create_client region: 'us-other-1' }
+ it { should put_object 'one.txt', host: /other\.s3\.(us-stubbed-1\.)?amazonaws.com/ }
end
describe 'Mapping', run: false do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 28d4ea356..c1a4df9f7 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -11,6 +11,7 @@
c.include Support::Env
c.include Support::File
c.include Support::Fixtures
+ c.include Support::Helpers
c.include Support::Matchers
c.include Support::Matchers::RecordCmds, record: true
c.include Support::Now
diff --git a/spec/support.rb b/spec/support.rb
index a0b78f7ff..519447d20 100644
--- a/spec/support.rb
+++ b/spec/support.rb
@@ -4,22 +4,7 @@
require 'support/file'
require 'support/fixtures'
require 'support/gemfile'
+require 'support/helpers'
require 'support/matchers'
require 'support/now'
require 'support/require'
-
-def stringify(obj)
- case obj
- when Hash then obj.map { |key, obj| [key.to_s, symbolize(obj)] }.to_h
- when Array then obj.map { |obj| symbolize(obj) }
- else obj
- end
-end
-
-def symbolize(obj)
- case obj
- when Hash then obj.map { |key, obj| [key.to_sym, symbolize(obj)] }.to_h
- when Array then obj.map { |obj| symbolize(obj) }
- else obj
- end
-end
diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb
new file mode 100644
index 000000000..51028f0ca
--- /dev/null
+++ b/spec/support/helpers.rb
@@ -0,0 +1,31 @@
+module Support
+ module Helpers
+ def only(hash, *keys)
+ hash.select { |key, _| keys.include?(key) }.to_h
+ end
+
+ def except(hash, *keys)
+ hash.reject { |key, _| keys.include?(key) }.to_h
+ end
+
+ def compact(hash)
+ hash.reject { |_, value| value.nil? }
+ end
+
+ def stringify(obj)
+ case obj
+ when Hash then obj.map { |key, obj| [key.to_s, stringify(obj)] }.to_h
+ when Array then obj.map { |obj| stringify(obj) }
+ else obj
+ end
+ end
+
+ def symbolize(obj)
+ case obj
+ when Hash then obj.map { |key, obj| [key.to_sym, symbolize(obj)] }.to_h
+ when Array then obj.map { |obj| symbolize(obj) }
+ else obj
+ end
+ end
+ end
+end
diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb
index ea5fe52d4..35d511d40 100644
--- a/spec/support/matchers.rb
+++ b/spec/support/matchers.rb
@@ -1,3 +1,4 @@
+require 'support/matchers/aws'
require 'support/matchers/have_deprecated'
require 'support/matchers/have_env'
require 'support/matchers/have_logged'
diff --git a/spec/support/matchers/aws.rb b/spec/support/matchers/aws.rb
new file mode 100644
index 000000000..cbf27f412
--- /dev/null
+++ b/spec/support/matchers/aws.rb
@@ -0,0 +1,192 @@
+module Support
+ module Matchers
+ module Aws
+ class Base < Struct.new(:opts)
+ include Support::Helpers, RSpec::Matchers::BuiltIn,
+ RSpec::Mocks::Matchers, RSpec::Mocks::ArgumentMatchers
+ end
+
+ class HaveRequested < Base
+ def matches?(*)
+ !!request
+ end
+
+ def description
+ "have requested #{operation}"
+ end
+
+ def failure_message
+ msg = "Expected the operation #{operation.inspect} to be requested#{" with #{format_opts}" if opts.any?}, but it wasn't."
+ msg << "\n\nInstead the following requests were made:\n\n #{format_requests}" if requests.any?
+ msg
+ end
+
+ def failure_message_when_negated
+ "Expected the operation #{operation.inspect} to not be requested#{" with #{format_opts}" if opts.any?}, but it was."
+ end
+
+ def request
+ host, path, body, file, headers = opts.values_at(:host, :path, :body, :file, :headers)
+ headers ||= except(opts, :host, :path, :body, :file, :client, :operation)
+ headers = stringify(headers)
+ reqs = requests.select { |r| r[:operation] == operation }
+ reqs = reqs.select { |r| match?(r[:host], host) } if host
+ reqs = reqs.select { |r| r[:path] == path } if path
+ reqs = reqs.select { |r| match?(r[:body], body) } if body
+ reqs = reqs.select { |r| r[:file] == file } if file
+ reqs = reqs.select { |r| include?(r[:headers], headers) } if headers
+ reqs.any? and reqs[0][:request]
+ end
+
+ def requests
+ client.api_requests.map do |req|
+ compact(
+ operation: req[:operation_name],
+ host: req[:context].http_request.endpoint.host,
+ path: req[:context].http_request.endpoint.path,
+ body: body_from(req[:context].http_request.body),
+ file: req[:params][:body] && req[:params][:body].path,
+ headers: req[:context].http_request.headers,
+ request: req[:context].http_request
+ )
+ end
+ end
+
+ def body_from(obj)
+ case obj
+ when StringIO
+ obj.string
+ when ::Aws::Query::ParamList::IoWrapper
+ obj.read
+ end
+ end
+
+ def format_opts
+ except(opts, :client, :operation).map { |pair| pair.join('=') }.join(' ')
+ end
+
+ def format_requests
+ requests.map { |r| except(r, :request).map { |key, value| [key, value.inspect].join(': ') }.join("\n ") }.join("\n\n")
+ end
+
+ def match?(actual, expected)
+ case expected
+ when String then actual.include?(expected)
+ when Regexp then actual =~ expected
+ when Hash then include?(JSON.parse(actual), stringify(expected))
+ end
+ end
+
+ def include?(hash, other)
+ # Include.new(other).matches?(hash)
+ other.all? do |key, value|
+ case value
+ when RSpec::Mocks::ArgumentMatchers::InstanceOf
+ # just can't get this working in any other way ...
+ hash[key].is_a?(value.instance_variable_get(:@klass))
+ when Hash
+ include?(hash[key], value)
+ else
+ hash[key] == value
+ end
+ end
+ end
+
+ def client
+ opts[:client]
+ end
+
+ def operation
+ opts[:operation]
+ end
+ end
+
+ class CreateClient < Base
+ def matches?(*)
+ matcher.matches?(::Aws::S3::Client)
+ end
+
+ def description
+ matcher.description
+ end
+
+ def failure_message
+ matcher.failure_message
+ end
+
+ def failure_message_when_negated
+ matcher.failure_message_when_negated
+ end
+
+ def matcher
+ @matchers ||= HaveReceived.new(:new).with(hash_including(opts))
+ end
+ end
+
+ def create_client(opts)
+ CreateClient.new(opts)
+ end
+
+ def have_requested(operation, opts = {})
+ HaveRequested.new(opts.merge(client: client, operation: operation))
+ end
+
+ # elasticbeanstalk
+
+ def create_app_version(body = nil)
+ have_requested(:create_application_version, compact(body: body))
+ end
+
+ def update_environment
+ have_requested(:update_environment)
+ end
+
+ # lambda
+
+ def create_function(params)
+ have_requested(:create_function, body: params)
+ end
+
+ def update_function_config(params)
+ have_requested(:update_function_configuration, body: params)
+ end
+
+ def update_function_code(params)
+ have_requested(:update_function_code, body: params)
+ end
+
+ def tag_resource(params)
+ have_requested(:tag_resource, body: params)
+ end
+
+ # codedeploy and opsworks
+
+ def create_deployment(params)
+ have_requested(:create_deployment, body: params)
+ end
+
+ def get_deployment
+ have_requested(:get_deployment)
+ end
+
+ def describe_deployments(params)
+ have_requested(:describe_deployments, body: params)
+ end
+
+ def update_app(params)
+ have_requested(:update_app, body: params)
+ end
+
+ # s3
+
+ def put_object(file, opts = {})
+ have_requested(:put_object, opts.merge(file: file))
+ end
+
+ def put_bucket_website_suffix(suffix)
+ have_requested(:put_bucket_website, body: %r(#{suffix}))
+ end
+ end
+ end
+end
+