defra_ruby_aws 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f98773dfc3468b835ccb7120609f527544bb794
4
+ data.tar.gz: 450ba740fa675f36bcd7b1c072524e06306e0f0f
5
+ SHA512:
6
+ metadata.gz: bce99a5fbe92846cdf796771c153b3a90d2fef9459458f87f89e6626b24011c3bff84f5a42ba8ef4e457fa9bc297e4c59e8774fffdb958d0573fc6a46f524fd3
7
+ data.tar.gz: 27d93f4cc90f7d8eb5445017a990215afec9e345d9121dd04243fd734854cfd8362c7c1403b7c8891199b26a236b0871c526b345075cd12c730957b28eba9f86
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # DefraRuby::Aws
2
+
3
+ [![Build Status](https://travis-ci.com/DEFRA/defra-ruby-aws.svg?branch=master)](https://travis-ci.com/DEFRA/defra-ruby-aws)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/4541a29b2c675b03a5ed/maintainability)](https://codeclimate.com/github/DEFRA/defra-ruby-aws/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/4541a29b2c675b03a5ed/test_coverage)](https://codeclimate.com/github/DEFRA/defra-ruby-aws/test_coverage)
6
+ [![security](https://hakiri.io/github/DEFRA/defra-ruby-aws/master.svg)](https://hakiri.io/github/DEFRA/defra-ruby-aws/master)
7
+ [![Gem Version](https://badge.fury.io/rb/defra_ruby_aws.svg)](https://badge.fury.io/rb/defra_ruby_aws)
8
+ [![Licence](https://img.shields.io/badge/Licence-OGLv3-blue.svg)](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)
9
+
10
+ Package of Ruby helpers for connecting Rails applications to AWS S3.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile
15
+
16
+ ```ruby
17
+ gem 'defra_ruby_aws'
18
+ ```
19
+
20
+ And then update your dependencies by calling
21
+
22
+ ```bash
23
+ bundle install
24
+ ```
25
+
26
+ ## Configuration
27
+
28
+ Add a new bucket with:
29
+
30
+ ```ruby
31
+ # config/initializers/defra_ruby_aws.rb
32
+ require "defra_ruby/aws"
33
+
34
+ DefraRuby::Aws.configure do |config|
35
+ config.buckets = [{
36
+ # bucket's name, required
37
+ name: "defra-ruby-aws",
38
+ # AWS bucket access credentials, required
39
+ credentials: {
40
+ access_key_id: "ACCESS_KEY_ID",
41
+ secret_access_key: "SECRET_ACCESS_KEY"
42
+ },
43
+ # optional - Default to "eu-west-1"
44
+ region: "eu-west-1"
45
+ }]
46
+ end
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Upload a file
52
+
53
+ ```ruby
54
+ file_to_upload = Tempfile.new("test-upload-file.csv")
55
+ bucket = DefraRuby::Aws.get_bucket("defra-ruby-aws")
56
+ response = bucket.load(file_to_upload)
57
+
58
+ if response.successful?
59
+ # Do something
60
+ else
61
+ response.error # return the failure error
62
+ # Do something else
63
+ end
64
+ ```
65
+
66
+ ### Generate a presigned URL for download
67
+
68
+ ```ruby
69
+ bucket = DefraRuby::Aws.get_bucket("defra-ruby-aws")
70
+ presigned_url = bucket.presigned_url("test-upload-file.csv")
71
+ ```
72
+
73
+ ## Contributing to this project
74
+
75
+ If you have an idea you'd like to contribute please log an issue.
76
+
77
+ All contributions should be submitted via a pull request.
78
+
79
+ ## License
80
+
81
+ THIS INFORMATION IS LICENSED UNDER THE CONDITIONS OF THE OPEN GOVERNMENT LICENCE found at:
82
+
83
+ http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3
84
+
85
+ The following attribution statement MUST be cited in your products and applications when using this information.
86
+
87
+ > Contains public sector information licensed under the Open Government license v3
88
+
89
+ ### About the license
90
+
91
+ The Open Government Licence (OGL) was developed by the Controller of Her Majesty's Stationery Office (HMSO) to enable information providers in the public sector to license the use and re-use of their information under a common open licence.
92
+
93
+ It is designed to encourage use and re-use of information freely and flexibly, with only a few conditions.
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ rescue LoadError
6
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
7
+ end
8
+
9
+ Bundler::GemHelper.install_tasks
10
+
11
+ # This is wrapped to prevent an error when rake is called in environments where
12
+ # rspec may not be available, e.g. production. As such we don't need to handle
13
+ # the error.
14
+ # rubocop:disable Lint/HandleExceptions
15
+ begin
16
+ require "rspec/core/rake_task"
17
+
18
+ RSpec::Core::RakeTask.new(:spec)
19
+
20
+ task default: :spec
21
+ rescue LoadError
22
+ # no rspec available
23
+ end
24
+
25
+ begin
26
+ require "github_changelog_generator/task"
27
+
28
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
29
+ end
30
+ rescue LoadError
31
+ # no changelog available
32
+ end
33
+ # rubocop:enable Lint/HandleExceptions
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "defra_ruby/aws"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/defra_ruby.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "defra_ruby/aws"
4
+
5
+ module DefraRuby
6
+ # The Defra Ruby packages namespace.
7
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "aws/bucket"
4
+ require_relative "aws/response"
5
+ require_relative "aws/configuration"
6
+
7
+ require_relative "aws/services/concerns/has_aws_bucket_configuration"
8
+ require_relative "aws/services/bucket_loader_service"
9
+ require_relative "aws/services/presigned_url_service"
10
+
11
+ module DefraRuby
12
+ module Aws
13
+ class << self
14
+ attr_accessor :configuration
15
+
16
+ def configure
17
+ require "aws-sdk-s3"
18
+
19
+ self.configuration ||= Configuration.new
20
+ yield(configuration)
21
+ end
22
+
23
+ def get_bucket(bucket_name)
24
+ configuration.buckets.select do |bucket|
25
+ bucket.bucket_name == bucket_name
26
+ end.first
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ class Bucket
6
+ attr_reader :bucket_name, :credentials, :region
7
+
8
+ def initialize(configs)
9
+ @credentials = configs[:credentials]
10
+ @bucket_name = configs[:name]
11
+ @region = setup_region(configs[:region])
12
+
13
+ validate!
14
+ end
15
+
16
+ def access_key_id
17
+ credentials[:access_key_id]
18
+ end
19
+
20
+ def secret_access_key
21
+ credentials[:secret_access_key]
22
+ end
23
+
24
+ def load(file)
25
+ BucketLoaderService.run(self, file)
26
+ end
27
+
28
+ def presigned_url(file_name)
29
+ PresignedUrlService.run(self, file_name)
30
+ end
31
+
32
+ private
33
+
34
+ attr_writer :region
35
+
36
+ def setup_region(region)
37
+ return default_region if region.nil? || region.empty?
38
+
39
+ region
40
+ end
41
+
42
+ def default_region
43
+ "eu-west-1"
44
+ end
45
+
46
+ def validate!
47
+ validate_presence_of_name!
48
+ validate_presence_of_credentials!
49
+ end
50
+
51
+ def validate_presence_of_name!
52
+ raise_not_valid_name if bucket_name.nil? || bucket_name.empty?
53
+ end
54
+
55
+ def validate_presence_of_credentials!
56
+ raise_missing_credentials if empty?(credentials)
57
+ raise_missing_access_key if empty?(access_key_id)
58
+ raise_missing_secret_access_key if empty?(secret_access_key)
59
+ end
60
+
61
+ def raise_not_valid_name
62
+ raise("DefraRuby::Aws buckets configurations: missing bucket name")
63
+ end
64
+
65
+ def raise_missing_credentials
66
+ raise("DefraRuby::Aws buckets configurations: missing credentials for bucket #{bucket_name}")
67
+ end
68
+
69
+ def raise_missing_access_key
70
+ raise("DefraRuby::Aws buckets configurations: missing access key id for bucket #{bucket_name}")
71
+ end
72
+
73
+ def raise_missing_secret_access_key
74
+ raise("DefraRuby::Aws buckets configurations: missing secret access key for bucket #{bucket_name}")
75
+ end
76
+
77
+ def empty?(object)
78
+ object.nil? || object.empty?
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ class Configuration
6
+ attr_reader :buckets
7
+
8
+ def initialize
9
+ @buckets = {}
10
+ end
11
+
12
+ def buckets=(buckets_configurations)
13
+ @buckets = buckets_configurations.map do |configs|
14
+ Bucket.new(configs)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ class Response
6
+ attr_reader :error
7
+
8
+ def initialize(response_exe)
9
+ @success = true
10
+ @error = nil
11
+
12
+ capture_response(response_exe)
13
+ end
14
+
15
+ def successful?
16
+ success
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :success
22
+
23
+ def capture_response(response_exe)
24
+ response_exe.call
25
+ rescue StandardError => e
26
+ @error = e
27
+ @success = false
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ class BucketLoaderService
6
+ include HasAwsBucketConfiguration
7
+
8
+ def self.run(bucket, file)
9
+ new(bucket, file).run
10
+ end
11
+
12
+ def initialize(bucket, file)
13
+ @bucket = bucket
14
+ @file = file
15
+ end
16
+
17
+ def run
18
+ Response.new(response_exe)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :bucket, :file
24
+
25
+ def response_exe
26
+ lambda do
27
+ s3_bucket.object(File.basename(file.path)).upload_file(file.path, server_side_encryption: :AES256)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ module HasAwsBucketConfiguration
6
+ def s3_bucket
7
+ s3.bucket(bucket.bucket_name)
8
+ end
9
+
10
+ def s3
11
+ ::Aws::S3::Resource.new(
12
+ region: bucket.region,
13
+ credentials: aws_credentials
14
+ )
15
+ end
16
+
17
+ def aws_credentials
18
+ ::Aws::Credentials.new(bucket.access_key_id, bucket.secret_access_key)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ class PresignedUrlService
6
+ include HasAwsBucketConfiguration
7
+
8
+ def self.run(bucket, file_name)
9
+ new(bucket, file_name).run
10
+ end
11
+
12
+ def initialize(bucket, file_name)
13
+ @bucket = bucket
14
+ @file_name = file_name
15
+ end
16
+
17
+ def run
18
+ s3_bucket.object(file_name).presigned_url(
19
+ :get,
20
+ expires_in: 20 * 60, # 20 minutes in seconds
21
+ secure: true,
22
+ response_content_type: "text/csv",
23
+ response_content_disposition: "attachment; filename=#{file_name}"
24
+ )
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :bucket, :file_name
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Aws
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe DefraRuby::Aws do
4
+ it "has a version number" do
5
+ expect(DefraRuby::Aws::VERSION).not_to be nil
6
+ end
7
+ end
data/spec/examples.txt ADDED
@@ -0,0 +1,17 @@
1
+ example_id | status | run_time |
2
+ ----------------------------------------------------------------------- | ------ | --------------- |
3
+ ./spec/defra_ruby_aws_spec.rb[1:1] | passed | 0.00122 seconds |
4
+ ./spec/features/upload_file_to_bucket_spec.rb[1:1] | passed | 0.0124 seconds |
5
+ ./spec/features/upload_file_to_bucket_spec.rb[1:2] | passed | 0.00574 seconds |
6
+ ./spec/lib/defra_ruby/aws/bucket_spec.rb[1:1:1:1] | passed | 0.00174 seconds |
7
+ ./spec/lib/defra_ruby/aws/bucket_spec.rb[1:1:2:1] | passed | 0.0001 seconds |
8
+ ./spec/lib/defra_ruby/aws/bucket_spec.rb[1:1:3:1] | passed | 0.00017 seconds |
9
+ ./spec/lib/defra_ruby/aws/bucket_spec.rb[1:1:4:1] | passed | 0.00014 seconds |
10
+ ./spec/lib/defra_ruby/aws/bucket_spec.rb[1:2:1] | passed | 0.00213 seconds |
11
+ ./spec/lib/defra_ruby/aws/configuration_spec.rb[1:1:1] | passed | 0.00061 seconds |
12
+ ./spec/lib/defra_ruby/aws/response_spec.rb[1:1:1:1] | passed | 0.00011 seconds |
13
+ ./spec/lib/defra_ruby/aws/response_spec.rb[1:1:2:1] | passed | 0.00014 seconds |
14
+ ./spec/lib/defra_ruby/aws/response_spec.rb[1:2:1:1] | passed | 0.0001 seconds |
15
+ ./spec/lib/defra_ruby/aws/response_spec.rb[1:2:2:1] | passed | 0.00011 seconds |
16
+ ./spec/lib/defra_ruby/aws/services/bucket_loader_service_spec.rb[1:1:1] | passed | 0.01269 seconds |
17
+ ./spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb[1:1:1] | passed | 0.00368 seconds |
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "Defra Ruby AWS" do
6
+ it "Upload a file to an AWS bucket" do
7
+ configure_gem
8
+ stub_successful_request
9
+
10
+ bucket = DefraRuby::Aws.get_bucket("bulk-test")
11
+ response = bucket.load(Tempfile.new("test-bucket-load.test"))
12
+
13
+ expect(response).to be_successful
14
+ end
15
+
16
+ it "fails gracefully" do
17
+ configure_gem
18
+ stub_failing_request
19
+
20
+ bucket = DefraRuby::Aws.get_bucket("bulk-test")
21
+ response = bucket.load(Tempfile.new("test-bucket-load.test"))
22
+
23
+ expect(response).to_not be_successful
24
+ expect(response.error).to be_a(Aws::S3::Errors::Forbidden)
25
+ end
26
+
27
+ def configure_gem
28
+ DefraRuby::Aws.configure do |config|
29
+ config.buckets = [{
30
+ name: "bulk-test",
31
+ credentials: {
32
+ access_key_id: "ACCESS_KEY_ID",
33
+ secret_access_key: "SECRET_ACCESS_KEY"
34
+ }
35
+ }]
36
+ end
37
+ end
38
+
39
+ def stub_successful_request
40
+ stub_request(:put, %r{https:\/\/bulk-test\.s3\.eu-west-1\.amazonaws\.com\/test-bucket-load\..+})
41
+ end
42
+
43
+ def stub_failing_request
44
+ stub_request(
45
+ :put,
46
+ %r{https:\/\/bulk-test\.s3\.eu-west-1\.amazonaws\.com\/test-bucket-load\..+}
47
+ ).to_return(
48
+ status: 403
49
+ )
50
+ end
51
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module DefraRuby
6
+ module Aws
7
+ RSpec.describe Bucket do
8
+ subject(:bucket) { described_class.new(configs) }
9
+
10
+ describe "#initialize" do
11
+ context "when a name configuration is missing" do
12
+ let(:configs) do
13
+ {
14
+ name: nil,
15
+ credentials: {}
16
+ }
17
+ end
18
+
19
+ it "raises an error" do
20
+ expect { bucket }.to raise_error("DefraRuby::Aws buckets configurations: missing bucket name")
21
+ end
22
+ end
23
+
24
+ context "when credentials configuration is missing" do
25
+ let(:configs) do
26
+ {
27
+ name: "foo",
28
+ credentials: {}
29
+ }
30
+ end
31
+
32
+ it "raises an error" do
33
+ expect { bucket }.to raise_error("DefraRuby::Aws buckets configurations: missing credentials for bucket foo")
34
+ end
35
+ end
36
+
37
+ context "when credentials access key id is missing" do
38
+ let(:configs) do
39
+ {
40
+ name: "foo",
41
+ credentials: {
42
+ secret_access_key: "secret"
43
+ }
44
+ }
45
+ end
46
+
47
+ it "raises an error" do
48
+ expect { bucket }.to raise_error("DefraRuby::Aws buckets configurations: missing access key id for bucket foo")
49
+ end
50
+ end
51
+
52
+ context "when credentials secret access key is missing" do
53
+ let(:configs) do
54
+ {
55
+ name: "foo",
56
+ credentials: {
57
+ access_key_id: "access_key"
58
+ }
59
+ }
60
+ end
61
+
62
+ it "raises an error" do
63
+ expect { bucket }.to raise_error("DefraRuby::Aws buckets configurations: missing secret access key for bucket foo")
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "#load" do
69
+ let(:configs) do
70
+ {
71
+ name: "foo",
72
+ credentials: {
73
+ secret_access_key: "secret",
74
+ access_key_id: "access_key"
75
+ }
76
+ }
77
+ end
78
+
79
+ it "loads the given file to the s3 bucket" do
80
+ result = double(:result)
81
+ file = double(:file)
82
+
83
+ expect(BucketLoaderService).to receive(:run).with(bucket, file).and_return(result)
84
+ expect(bucket.load(file)).to eq(result)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module DefraRuby
6
+ module Aws
7
+ RSpec.describe Configuration do
8
+ subject(:configuration) { described_class.new }
9
+
10
+ describe "#buckets=" do
11
+ let(:buckets) { %i[foo bar baz] }
12
+
13
+ it "creates a list of buckets" do
14
+ expect(Bucket).to receive(:new).with(:foo)
15
+ expect(Bucket).to receive(:new).with(:bar)
16
+ expect(Bucket).to receive(:new).with(:baz)
17
+
18
+ configuration.buckets = buckets
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module DefraRuby
6
+ module Aws
7
+ RSpec.describe Response do
8
+ subject(:response) { described_class.new(response_exe) }
9
+
10
+ describe "#successful?" do
11
+ context "when the response throws an error" do
12
+ let(:response_exe) { -> { raise "Boom!" } }
13
+
14
+ it "returns false" do
15
+ expect(response).to_not be_successful
16
+ end
17
+ end
18
+
19
+ context "when the response don't throw an error" do
20
+ let(:response_exe) { -> {} }
21
+
22
+ it "returns true" do
23
+ expect(response).to be_successful
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "#error" do
29
+ context "when the response throws an error" do
30
+ let(:response_exe) { -> { raise StandardError, "Boom!" } }
31
+
32
+ it "returns the error" do
33
+ expect(response.error).to be_a(StandardError)
34
+ end
35
+ end
36
+
37
+ context "when the response don't throw an error" do
38
+ let(:response_exe) { -> {} }
39
+
40
+ it "returns a nil object" do
41
+ expect(response.error).to be_nil
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module DefraRuby
6
+ module Aws
7
+ RSpec.describe BucketLoaderService do
8
+ describe "#run" do
9
+ let(:configs) do
10
+ {
11
+ credentials: {
12
+ access_key_id: "key_id",
13
+ secret_access_key: "secret"
14
+ },
15
+ name: "bulk"
16
+ }
17
+ end
18
+ let(:bucket) { Bucket.new(configs) }
19
+
20
+ it "loads the given file to the s3 bucket" do
21
+ aws_resource = double(:aws_resource)
22
+ s3_bucket = double(:s3_bulk_bucket)
23
+ file = double(:file, path: "foo/bar/baz/test.csv")
24
+ s3_object = double(:s3_object)
25
+ result = double(:result)
26
+
27
+ expect(::Aws::S3::Resource).to receive(:new).and_return(aws_resource)
28
+ expect(aws_resource).to receive(:bucket).with("bulk").and_return(s3_bucket)
29
+ expect(s3_bucket).to receive(:object).with("test.csv").and_return(s3_object)
30
+ expect(s3_object).to receive(:upload_file).with("foo/bar/baz/test.csv", server_side_encryption: :AES256).and_return(result)
31
+
32
+ expect(described_class.run(bucket, file)).to be_a(Response)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module DefraRuby
6
+ module Aws
7
+ RSpec.describe PresignedUrlService do
8
+ describe ".run" do
9
+ let(:configs) do
10
+ {
11
+ name: "test",
12
+ credentials: {
13
+ access_key_id: "123",
14
+ secret_access_key: "Secret"
15
+ }
16
+ }
17
+ end
18
+ let(:bucket) { Bucket.new(configs) }
19
+ let(:presigned_url) { described_class.run(bucket, "testfile.csv") }
20
+
21
+ it "returns a presigned url for a given file in the bucket" do
22
+ expect(presigned_url).to include("https://test.s3.eu-west-1.amazonaws.com/testfile.csv")
23
+ expect(presigned_url).to include("response-content-disposition=attachment")
24
+ expect(presigned_url).to include("response-content-type=text%2Fcsv")
25
+ expect(presigned_url).to include("Amz-Expires")
26
+ expect(presigned_url).to include("Amz-Credential")
27
+ expect(presigned_url).to include("Amz-Signature")
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+
5
+ # Require and run our simplecov initializer as the very first thing we do.
6
+ # This is as per its docs https://github.com/colszowka/simplecov#getting-started
7
+ require "./spec/support/simplecov"
8
+
9
+ # Requires supporting ruby files with custom matchers and macros, etc, in
10
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
11
+ # run as spec files by default. This means that files in spec/support that end
12
+ # in _spec.rb will both be required and run as specs, causing the specs to be
13
+ # run twice. It is recommended that you do not name files matching this glob to
14
+ # end with _spec.rb. You can configure this pattern with the --pattern
15
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
16
+ #
17
+ # We make an exception for simplecov because that will already have been
18
+ # required and run at the very top of spec_helper.rb
19
+ support_files = Dir["./spec/support/**/*.rb"].reject { |file| file == "./spec/support/simplecov.rb" }
20
+ support_files.each { |f| require f }
21
+
22
+ RSpec.configure do |config|
23
+ # rspec-expectations config goes here. You can use an alternate
24
+ # assertion/expectation library such as wrong or the stdlib/minitest
25
+ # assertions if you prefer.
26
+ config.expect_with :rspec do |expectations|
27
+ # This option will default to `true` in RSpec 4. It makes the `description`
28
+ # and `failure_message` of custom matchers include text for helper methods
29
+ # defined using `chain`, e.g.:
30
+ # be_bigger_than(2).and_smaller_than(4).description
31
+ # # => "be bigger than 2 and smaller than 4"
32
+ # ...rather than:
33
+ # # => "be bigger than 2"
34
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
35
+ end
36
+
37
+ # rspec-mocks config goes here. You can use an alternate test double
38
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
39
+ config.mock_with :rspec do |mocks|
40
+ # Prevents you from mocking or stubbing a method that does not exist on
41
+ # a real object. This is generally recommended, and will default to
42
+ # `true` in RSpec 4.
43
+ mocks.verify_partial_doubles = true
44
+ end
45
+
46
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
47
+ # have no way to turn it off -- the option exists only for backwards
48
+ # compatibility in RSpec 3). It causes shared context metadata to be
49
+ # inherited by the metadata hash of host groups and examples, rather than
50
+ # triggering implicit auto-inclusion in groups with matching metadata.
51
+ config.shared_context_metadata_behavior = :apply_to_host_groups
52
+
53
+ # This allows you to limit a spec run to individual examples or groups
54
+ # you care about by tagging them with `:focus` metadata. When nothing
55
+ # is tagged with `:focus`, all examples get run. RSpec also provides
56
+ # aliases for `it`, `describe`, and `context` that include `:focus`
57
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
58
+ config.filter_run_when_matching :focus
59
+
60
+ # Allows RSpec to persist some state between runs in order to support
61
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
62
+ # you configure your source control system to ignore this file.
63
+ config.example_status_persistence_file_path = "spec/examples.txt"
64
+
65
+ # Limits the available syntax to the non-monkey patched syntax that is
66
+ # recommended. For more details, see:
67
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
68
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
70
+ config.disable_monkey_patching!
71
+
72
+ # Run specs in random order to surface order dependencies. If you find an
73
+ # order dependency and want to debug it, you can fix the order by providing
74
+ # the seed, which is printed after each run.
75
+ # --seed 1234
76
+ config.order = :random
77
+
78
+ # Seed global randomization in this process using the `--seed` CLI option.
79
+ # Setting this allows you to use `--seed` to deterministically reproduce
80
+ # test failures related to randomization by passing the same `--seed` value
81
+ # as the one that triggered the failure.
82
+ Kernel.srand config.seed
83
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Gem that allows us to integrate with AWS S3 (cloud storage)
4
+ require "aws-sdk-s3"
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load env vars from a text file
4
+ require "dotenv/load"
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Support debugging in the tests. Add `binding.pry` wherever you want execution
4
+ # to stop and the debugger to kick in.
5
+ # Details on the debugging commands can be found here
6
+ # https://github.com/deivid-rodriguez/pry-byebug#commands
7
+ require "pry-byebug"
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "simplecov"
4
+
5
+ # We start it with the rails param to ensure it includes coverage for all code
6
+ # started by the rails app, and not just the files touched by our unit tests.
7
+ # This gives us the most accurate assessment of our unit test coverage
8
+ # https://github.com/colszowka/simplecov#getting-started
9
+ SimpleCov.start do
10
+ # The version file is simply just that, so we do not feel the need to ensure
11
+ # we have a test for it
12
+ add_filter "lib/defra_ruby/aws/version"
13
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Library for stubbing and setting expectations on HTTP requests in Ruby
4
+ require "webmock/rspec"
metadata ADDED
@@ -0,0 +1,212 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: defra_ruby_aws
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Defra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-s3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: defra_ruby_style
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: github_changelog_generator
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Package of AWS features commonly used in Defra Rails based digital services
140
+ email:
141
+ - alan.cruikshanks@environment-agency.gov.uk
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - README.md
147
+ - Rakefile
148
+ - bin/console
149
+ - bin/setup
150
+ - lib/defra_ruby.rb
151
+ - lib/defra_ruby/aws.rb
152
+ - lib/defra_ruby/aws/bucket.rb
153
+ - lib/defra_ruby/aws/configuration.rb
154
+ - lib/defra_ruby/aws/response.rb
155
+ - lib/defra_ruby/aws/services/bucket_loader_service.rb
156
+ - lib/defra_ruby/aws/services/concerns/has_aws_bucket_configuration.rb
157
+ - lib/defra_ruby/aws/services/presigned_url_service.rb
158
+ - lib/defra_ruby/aws/version.rb
159
+ - spec/defra_ruby_aws_spec.rb
160
+ - spec/examples.txt
161
+ - spec/features/upload_file_to_bucket_spec.rb
162
+ - spec/lib/defra_ruby/aws/bucket_spec.rb
163
+ - spec/lib/defra_ruby/aws/configuration_spec.rb
164
+ - spec/lib/defra_ruby/aws/response_spec.rb
165
+ - spec/lib/defra_ruby/aws/services/bucket_loader_service_spec.rb
166
+ - spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb
167
+ - spec/spec_helper.rb
168
+ - spec/support/aws_sdk_s3.rb
169
+ - spec/support/dotenv.rb
170
+ - spec/support/pry.rb
171
+ - spec/support/simplecov.rb
172
+ - spec/support/webmock.rb
173
+ homepage: https://github.com/DEFRA/defra-ruby-aws
174
+ licenses:
175
+ - The Open Government Licence (OGL) Version 3
176
+ metadata:
177
+ allowed_push_host: https://rubygems.org
178
+ post_install_message:
179
+ rdoc_options: []
180
+ require_paths:
181
+ - lib
182
+ required_ruby_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ requirements: []
193
+ rubyforge_project:
194
+ rubygems_version: 2.6.13
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Defra ruby on rails AWS helpers
198
+ test_files:
199
+ - spec/defra_ruby_aws_spec.rb
200
+ - spec/spec_helper.rb
201
+ - spec/examples.txt
202
+ - spec/features/upload_file_to_bucket_spec.rb
203
+ - spec/support/aws_sdk_s3.rb
204
+ - spec/support/simplecov.rb
205
+ - spec/support/webmock.rb
206
+ - spec/support/pry.rb
207
+ - spec/support/dotenv.rb
208
+ - spec/lib/defra_ruby/aws/configuration_spec.rb
209
+ - spec/lib/defra_ruby/aws/response_spec.rb
210
+ - spec/lib/defra_ruby/aws/bucket_spec.rb
211
+ - spec/lib/defra_ruby/aws/services/bucket_loader_service_spec.rb
212
+ - spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb