asset_cloud 2.2.6 → 2.2.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8da870cd7f0377f18b1ae46d7a4e8e69c2e4549f224e28df123f565d9e454d3
4
- data.tar.gz: 190fea72f1ef76ffa7aad5931324be4cfc172903f41826a1485c2e859fae50dc
3
+ metadata.gz: d356abcae5568be4981cdcbb779ba94471a67f942f048ee96119e9b9260cf366
4
+ data.tar.gz: 3923b527fe0e5c7e670641f53c6397723465a02877431b50e8e7da20bc67ee74
5
5
  SHA512:
6
- metadata.gz: fb1dff12c4fb90328182f23c96daf17f3f9fddbc13c42dd569b0855545c4be0621aa8bd218c43fc57eb44716f27026e1ca703fea67cd214231ee654853decca6
7
- data.tar.gz: e29ebc045b6eeac9705f5f758aca3fce768c6e9f8085ecc0502cbdecf1037621b504ab0c3c175f61e8faa912d16d5abef16f79c90941c02bbce865e8cc50cae1
6
+ metadata.gz: e8f3a5c2252c2cd574fc55e4feb4aa205a3340e8a43cb945414740be9f6313d422ecc241a8cb8279e48f7b32b6695817576f95779107dd072543c0024d69b33f
7
+ data.tar.gz: 480ada19cbcddae3f9acc2fc46d1022d82b3ba7582534b91aa9f0fe6dc0bbae9efa70f09f5fafd64b95be3e39601ec2b88d2d3bb34b10fe0fe8b7c540f5d0603
@@ -2,5 +2,5 @@ language: ruby
2
2
  before_install:
3
3
  - gem install bundler
4
4
  rvm:
5
- - '2.2'
6
5
  - '2.3'
6
+ - '2.6'
data/Gemfile CHANGED
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'aws-sdk', '~> 1.34.0', :require => nil
4
+ gem 'google-cloud-storage'
4
5
 
5
6
  gemspec
@@ -18,6 +18,10 @@ With S3 Remote test:
18
18
 
19
19
  AWS_ACCESS_KEY_ID="<s3_key>" AWS_SECRET_ACCESS_KEY="<s3_secret_key>" S3_BUCKET_NAME="<bucket_name>" bundle exec rake spec
20
20
 
21
+ With GCS Remote test:
22
+
23
+ GCS_PROJECT_ID="<project_id>" GCS_KEY_FILEPATH="<path_to_key>" GCS_BUCKET="<bucket_name>" bundle exec rake spec
24
+
21
25
  == Copyright
22
26
 
23
27
  Copyright (c) 2008-2014 Tobias Lütke & Shopify, Inc. Released under the MIT license (see LICENSE for details).
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{asset_cloud}
5
- s.version = "2.2.6"
5
+ s.version = "2.2.7"
6
6
 
7
7
  s.authors = %w(Shopify)
8
8
  s.summary = %q{An abstraction layer around arbitrary and diverse asset stores.}
@@ -16,6 +16,9 @@ require 'asset_cloud/base'
16
16
  # S3
17
17
  require 'asset_cloud/buckets/s3_bucket'
18
18
 
19
+ # GCS
20
+ require 'asset_cloud/buckets/gcs_bucket'
21
+
19
22
  # Extensions
20
23
  require 'asset_cloud/free_key_locator'
21
24
  require 'asset_cloud/callbacks'
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AssetCloud
4
+ class GCSBucket < Bucket
5
+ def ls(key = nil)
6
+ key ? find_by_key!(key) : bucket.files
7
+ end
8
+
9
+ def read(key)
10
+ file = find_by_key!(key)
11
+ downloaded = file.download
12
+ downloaded.rewind
13
+ downloaded.read
14
+ end
15
+
16
+ def write(key, data)
17
+ bucket.create_file(data, absolute_key(key))
18
+ end
19
+
20
+ def delete(key)
21
+ file = find_by_key!(key)
22
+ file.delete
23
+ end
24
+
25
+ def clear
26
+ bucket.files.each(&:delete)
27
+ end
28
+
29
+ def stat(key)
30
+ begin
31
+ file = find_by_key!(key)
32
+ Metadata.new(true, file.size, file.created_at, file.updated_at)
33
+ rescue AssetCloud::AssetNotFoundError
34
+ Metadata.new(false)
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def bucket
41
+ @bucket ||= cloud.gcs_bucket
42
+ end
43
+
44
+ def absolute_key(key = nil)
45
+ if key.to_s.starts_with?(path_prefix)
46
+ return key
47
+ else
48
+ args = [path_prefix]
49
+ args << key.to_s if key
50
+ args.join('/')
51
+ end
52
+ end
53
+
54
+ def path_prefix
55
+ @path_prefix ||= "s#{@cloud.url}"
56
+ end
57
+
58
+ def find_by_key!(key)
59
+ file = bucket.file(absolute_key(key))
60
+
61
+ raise AssetCloud::AssetNotFoundError, key unless file
62
+
63
+ file
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:disable RSpec/FilePath, Lint/MissingCopEnableDirective
3
+
4
+ require 'spec_helper'
5
+ require 'google/cloud/storage'
6
+
7
+ class RemoteGCSCloud < AssetCloud::Base
8
+ attr_accessor :gcs_connection
9
+ bucket :tmp, AssetCloud::GCSBucket
10
+
11
+ def gcs_bucket
12
+ gcs_connection.bucket(ENV['GCS_BUCKET'])
13
+ end
14
+ end
15
+
16
+ describe AssetCloud::GCSBucket, if: ENV['GCS_PROJECT_ID'] && ENV['GCS_KEY_FILEPATH'] && ENV['GCS_BUCKET'] do
17
+ directory = File.dirname(__FILE__) + '/files'
18
+
19
+ before(:all) do
20
+ @cloud = RemoteGCSCloud.new(directory, 'assets/files')
21
+
22
+ @cloud.gcs_connection = Google::Cloud::Storage.new(
23
+ project_id: ENV['GCS_PROJECT_ID'],
24
+ credentials: ENV['GCS_KEY_FILEPATH']
25
+ )
26
+ @bucket = @cloud.buckets[:tmp]
27
+ end
28
+
29
+ after(:all) do
30
+ @bucket.clear
31
+ end
32
+
33
+ it "#ls with no arguments returns all files in the bucket" do
34
+ expect_any_instance_of(Google::Cloud::Storage::Bucket).to receive(:files).with(no_args)
35
+ expect do
36
+ @bucket.ls
37
+ end.not_to raise_error
38
+ end
39
+
40
+ it "#ls with arguments returns the file" do
41
+ local_path = "#{directory}/products/key.txt"
42
+ key = 'test/ls.txt'
43
+
44
+ @bucket.write(key, local_path)
45
+
46
+ file = @bucket.ls(key)
47
+ expect(file.name).to eq("s#{@cloud.url}/#{key}")
48
+ end
49
+
50
+ it "#write writes a file into the bucket" do
51
+ local_path = "#{directory}/products/key.txt"
52
+ key = 'test/key.txt'
53
+
54
+ @bucket.write(key, local_path)
55
+ end
56
+
57
+ it "#delete removes the file from the bucket" do
58
+ key = 'test/key.txt'
59
+
60
+ expect do
61
+ @bucket.delete(key)
62
+ end.not_to raise_error
63
+ end
64
+
65
+ it "#delete raises AssetCloud::AssetNotFoundError if the file is not found" do
66
+ key = 'tmp/not_found.txt'
67
+ expect do
68
+ @bucket.delete(key)
69
+ end.to raise_error(AssetCloud::AssetNotFoundError)
70
+ end
71
+
72
+ it "#read returns the data of the file" do
73
+ value = 'hello world'
74
+ key = 'tmp/new_file.txt'
75
+ @bucket.write(key, StringIO.new(value))
76
+
77
+ data = @bucket.read(key)
78
+ data.should == value
79
+ end
80
+
81
+ it "#read raises AssetCloud::AssetNotFoundError if the file is not found" do
82
+ key = 'tmp/not_found.txt'
83
+ expect do
84
+ @bucket.read(key)
85
+ end.to raise_error(AssetCloud::AssetNotFoundError)
86
+ end
87
+
88
+ it "#stats returns metadata of the asset" do
89
+ value = 'hello world'
90
+ key = 'tmp/new_file.txt'
91
+ @bucket.write(key, StringIO.new(value))
92
+
93
+ stats = @bucket.stat(key)
94
+
95
+ expect(stats.size).not_to be_nil
96
+ expect(stats.created_at).not_to be_nil
97
+ expect(stats.updated_at).not_to be_nil
98
+ end
99
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+ require 'google/cloud/storage'
3
+
4
+ class GCSCloud < AssetCloud::Base
5
+ end
6
+
7
+ class MockGCSBucket < AssetCloud::GCSBucket
8
+ def files(prefix: nil)
9
+ end
10
+
11
+ def file(key)
12
+ end
13
+
14
+ def create_file(data, key)
15
+ end
16
+ end
17
+
18
+ describe AssetCloud::GCSBucket do
19
+ directory = File.dirname(__FILE__) + '/files'
20
+
21
+ before(:all) do
22
+ @cloud = GCSCloud.new(directory, '/assets/files')
23
+ @bucket = MockGCSBucket.new(@cloud, '')
24
+ end
25
+
26
+ it "#ls with no arguments returns all files in the bucket" do
27
+ expect_any_instance_of(GCSCloud).to receive(:gcs_bucket).and_return(@bucket)
28
+ expect_any_instance_of(MockGCSBucket).to receive(:files).with(no_args).and_return(nil)
29
+ @bucket.ls
30
+ end
31
+
32
+ it "#ls with arguments returns the file" do
33
+ key = 'test/ls.txt'
34
+ expect_any_instance_of(MockGCSBucket).to receive(:file).with("s#{@cloud.url}/#{key}").and_return(Google::Cloud::Storage::File.new)
35
+
36
+ file = @bucket.ls(key)
37
+ expect(file.class).to eq(Google::Cloud::Storage::File)
38
+ end
39
+
40
+ it "#write writes a file into the bucket" do
41
+ local_path = "#{directory}/products/key.txt"
42
+ key = 'test/key.txt'
43
+ expect_any_instance_of(MockGCSBucket).to receive(:create_file).with(local_path, "s#{@cloud.url}/#{key}")
44
+
45
+ @bucket.write(key, local_path)
46
+ end
47
+
48
+ it "#delete removes the file from the bucket" do
49
+ key = 'test/key.txt'
50
+ expect_any_instance_of(MockGCSBucket).to receive(:file).with("s#{@cloud.url}/#{key}").and_return(Google::Cloud::Storage::File.new)
51
+ expect_any_instance_of(Google::Cloud::Storage::File).to receive(:delete).with(no_args)
52
+
53
+ expect do
54
+ @bucket.delete(key)
55
+ end.not_to raise_error
56
+ end
57
+
58
+ it "#read returns the data of the file" do
59
+ value = 'hello world'
60
+ key = 'tmp/new_file.txt'
61
+ expect_any_instance_of(MockGCSBucket).to receive(:file).with("s#{@cloud.url}/#{key}").and_return(Google::Cloud::Storage::File.new)
62
+ expect_any_instance_of(Google::Cloud::Storage::File).to receive(:download).and_return(StringIO.new(value))
63
+
64
+ data = @bucket.read(key)
65
+ data.should == value
66
+ end
67
+
68
+ it "#read raises AssetCloud::AssetNotFoundError if the file is not found" do
69
+ key = 'tmp/not_found.txt'
70
+ expect_any_instance_of(MockGCSBucket).to receive(:file).with("s#{@cloud.url}/#{key}").and_return(nil)
71
+ expect do
72
+ @bucket.read(key)
73
+ end.to raise_error(AssetCloud::AssetNotFoundError)
74
+ end
75
+
76
+ it "#stat returns information on the asset" do
77
+ value = 'hello world'
78
+ key = 'tmp/new_file.txt'
79
+ expected_time = Time.now
80
+ expected_size = 1
81
+
82
+ expect_any_instance_of(MockGCSBucket).to receive(:file).with("s#{@cloud.url}/#{key}").and_return(Google::Cloud::Storage::File.new)
83
+ expect_any_instance_of(Google::Cloud::Storage::File).to receive(:size).and_return(expected_size)
84
+ expect_any_instance_of(Google::Cloud::Storage::File).to receive(:created_at).and_return(expected_time)
85
+ expect_any_instance_of(Google::Cloud::Storage::File).to receive(:updated_at).and_return(expected_time)
86
+
87
+ stats = @bucket.stat(key)
88
+ expect(stats.size).to eq(expected_size)
89
+ expect(stats.created_at).to eq(expected_time)
90
+ expect(stats.updated_at).to eq(expected_time)
91
+ end
92
+ end
@@ -5,3 +5,4 @@ require 'active_support/all'
5
5
  $:<< File.dirname(__FILE__) + "/../lib"
6
6
  require 'asset_cloud'
7
7
  require 'asset_cloud/buckets/s3_bucket'
8
+ require 'asset_cloud/buckets/gcs_bucket'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asset_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.6
4
+ version: 2.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-09 00:00:00.000000000 Z
11
+ date: 2019-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -119,6 +119,7 @@ files:
119
119
  - lib/asset_cloud/buckets/blackhole_bucket.rb
120
120
  - lib/asset_cloud/buckets/bucket_chain.rb
121
121
  - lib/asset_cloud/buckets/file_system_bucket.rb
122
+ - lib/asset_cloud/buckets/gcs_bucket.rb
122
123
  - lib/asset_cloud/buckets/invalid_bucket.rb
123
124
  - lib/asset_cloud/buckets/memory_bucket.rb
124
125
  - lib/asset_cloud/buckets/s3_bucket.rb
@@ -140,6 +141,8 @@ files:
140
141
  - spec/files/products/key.txt
141
142
  - spec/files/versioned_stuff/foo
142
143
  - spec/find_free_key_spec.rb
144
+ - spec/gcs_bucket_remote_spec.rb
145
+ - spec/gcs_bucket_spec.rb
143
146
  - spec/memory_bucket_spec.rb
144
147
  - spec/mock_s3_interface.rb
145
148
  - spec/remote_s3_bucket_spec.rb
@@ -165,8 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
168
  - !ruby/object:Gem::Version
166
169
  version: '0'
167
170
  requirements: []
168
- rubyforge_project:
169
- rubygems_version: 2.7.6
171
+ rubygems_version: 3.0.3
170
172
  signing_key:
171
173
  specification_version: 4
172
174
  summary: An abstraction layer around arbitrary and diverse asset stores.
@@ -183,6 +185,8 @@ test_files:
183
185
  - spec/files/products/key.txt
184
186
  - spec/files/versioned_stuff/foo
185
187
  - spec/find_free_key_spec.rb
188
+ - spec/gcs_bucket_remote_spec.rb
189
+ - spec/gcs_bucket_spec.rb
186
190
  - spec/memory_bucket_spec.rb
187
191
  - spec/mock_s3_interface.rb
188
192
  - spec/remote_s3_bucket_spec.rb