activestorage-openstack 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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +79 -0
- data/Rakefile +27 -0
- data/lib/active_storage/openstack.rb +7 -0
- data/lib/active_storage/openstack/railtie.rb +6 -0
- data/lib/active_storage/openstack/version.rb +5 -0
- data/lib/active_storage/service/open_stack_service.rb +141 -0
- data/lib/tasks/activestorage/openstack_tasks.rake +4 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 679f589974232f4e10a8668beca5099273e6f5a1f2595eb2f4d3298cef4a4dcf
|
4
|
+
data.tar.gz: b67c2107534d6208a65b867e98559738ce2bb8ec32854f0b1582f33cf9d03929
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bdc68784986e569e426386d2f9da663766ea9b0ab56b577d85fb9d1fbb4094f322a361017900b51b9886c6d5e2b29fd1cddf35cc218f182b4344cff5e62ae45f
|
7
|
+
data.tar.gz: f27590fc1462ed17c7681032dbc84734ce7a98b65fa839bd9e2a843d7dab390949f8c680d75d32076b9fac3e1d0a1c0f7d782c3db31e380ffa85977e216b7e4a
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 chaadow
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# ActiveStorage::Openstack
|
2
|
+
This rails plugin wraps the OpenStack Swift provider as an Active Storage service.
|
3
|
+
It is a rewrite/refactor of [activestorage-openstack](https://github.com/jeffreyguenther/activestorage-openstack).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'activestorage-openstack'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
```bash
|
14
|
+
$ bundle
|
15
|
+
```
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
```bash
|
19
|
+
$ gem install activestorage-openstack
|
20
|
+
```
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
in `config/storage.yml`, in your Rails app, create an entry with the following keys:
|
24
|
+
```yaml
|
25
|
+
dev_openstack:
|
26
|
+
service: OpenStack
|
27
|
+
container: <container name> # Container name for your OpenStack provider
|
28
|
+
credentials:
|
29
|
+
openstack_auth_url: <auth url>
|
30
|
+
openstack_username: <username>
|
31
|
+
openstack_api_key: <password>
|
32
|
+
openstack_region: <region>
|
33
|
+
openstack_temp_url_key: <temp url key> # Mandatory, instructions below
|
34
|
+
connection_options: # optional
|
35
|
+
chunk_size: 2097152 # 2MBs - 1MB is the default
|
36
|
+
```
|
37
|
+
|
38
|
+
You can create as many entries as you would like for your different environments. For instance: `dev_openstack` for development, `test_openstack` for test environment, and `prod_openstack` for production. This way you can choose the appropriate container for each scenario.
|
39
|
+
|
40
|
+
Then register the provider in your `config/{environment}.rb` (`config/development.rb`/`config/test.rb`/`config/production.rb`)
|
41
|
+
|
42
|
+
For example, for the `dev_openstack` entry above, change the `config` variable in `config/development.rb` like the following:
|
43
|
+
```ruby
|
44
|
+
# Store uploaded files on the local file system (see config/storage.yml for options)
|
45
|
+
config.active_storage.service = :dev_openstack
|
46
|
+
```
|
47
|
+
## Setting up a container
|
48
|
+
|
49
|
+
From your OpenStack provider website, create or sign in to your account.
|
50
|
+
Then from your dashboard, create a container, and save the configuration generated.
|
51
|
+
|
52
|
+
It is a good practice to create a separate container for each of your environments.
|
53
|
+
Once safely saved, you can add them to your storage configuration in your Rails application.
|
54
|
+
## `temp_url_key` configuration
|
55
|
+
|
56
|
+
the `openstack_temp_url_key` in your configuration is mandatory for generating URLs (expiring ones) as well as for Direct Upload. You can set it up with `Swift` or with the `Fog/OpenStack` gem. More instructions on how to set it up with Swift are found [HERE](https://docs.openstack.org/swift/latest/api/temporary_url_middleware.html#secret-keys)
|
57
|
+
|
58
|
+
The next version of this plugin, will add a rails generator, or expose a method that would use the built-in method from `Fog::OpenStack::Real` to generate the key.
|
59
|
+
|
60
|
+
## Testing
|
61
|
+
First, run `bundle` to install the gem dependencies (both development and production)
|
62
|
+
```bash
|
63
|
+
$ bundle
|
64
|
+
```
|
65
|
+
Then, from the root of the plugin, copy the following file and fill in the appropriate credentials.
|
66
|
+
**Preferably, set up a container for your testing, separate from production.**
|
67
|
+
```bash
|
68
|
+
$ cp test/configurations.example.yml test/configurations.yml
|
69
|
+
```
|
70
|
+
And then run the tests:
|
71
|
+
```bash
|
72
|
+
$ bin/test
|
73
|
+
```
|
74
|
+
|
75
|
+
## Contributions
|
76
|
+
Contributions are welcome. Feel free to open any issues if you encounter any bug, or if you want to suggest a feature by clicking here: https://github.com/chaadow/activestorage-openstack/issues
|
77
|
+
|
78
|
+
## License
|
79
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'ActiveStorage::Openstack'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'bundler/gem_tasks'
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
22
|
+
t.libs << 'test'
|
23
|
+
t.pattern = 'test/**/*_test.rb'
|
24
|
+
t.verbose = false
|
25
|
+
end
|
26
|
+
|
27
|
+
task default: :test
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'fog/openstack'
|
2
|
+
|
3
|
+
module ActiveStorage
|
4
|
+
class Service::OpenStackService < Service
|
5
|
+
attr_reader :client, :container
|
6
|
+
|
7
|
+
def initialize(container:, credentials:, connection_options: {})
|
8
|
+
settings = if connection_options.present?
|
9
|
+
credentials.reverse_merge(connection_options: connection_options)
|
10
|
+
else
|
11
|
+
credentials
|
12
|
+
end
|
13
|
+
@client = Fog::Storage::OpenStack.new(settings)
|
14
|
+
@container = Fog::OpenStack.escape(container)
|
15
|
+
end
|
16
|
+
|
17
|
+
def upload(key, io, checksum: nil)
|
18
|
+
instrument :upload, key: key, checksum: checksum do
|
19
|
+
params = {}.merge(etag: convert_base64digest_to_hexdigest(checksum))
|
20
|
+
begin
|
21
|
+
client.put_object(container, key, io, params)
|
22
|
+
rescue Excon::Error::UnprocessableEntity
|
23
|
+
raise ActiveStorage::IntegrityError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def download(key, &block)
|
29
|
+
if block_given?
|
30
|
+
instrument :streaming_download, key: key do
|
31
|
+
object_for(key, &block).body
|
32
|
+
end
|
33
|
+
else
|
34
|
+
instrument :download, key: key do
|
35
|
+
object_for(key).body
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def download_chunk(key, range)
|
41
|
+
instrument :download_chunk, key: key, range: range do
|
42
|
+
object_for(key).body[range]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(key)
|
47
|
+
instrument :delete, key: key do
|
48
|
+
begin
|
49
|
+
client.delete_object(container, key)
|
50
|
+
rescue Fog::Storage::OpenStack::NotFound
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_prefixed(prefix)
|
57
|
+
instrument :delete, prefix: prefix do
|
58
|
+
directory = client.directories.get(container)
|
59
|
+
filtered_files = client.files(directory: directory, prefix: prefix)
|
60
|
+
filtered_files = filtered_files.map(&:key)
|
61
|
+
|
62
|
+
client.delete_multiple_objects(container, filtered_files)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def exist?(key)
|
67
|
+
instrument :exist, key: key do |payload|
|
68
|
+
begin
|
69
|
+
answer = object_for(key)
|
70
|
+
payload[:exist] = answer
|
71
|
+
rescue Fog::Storage::OpenStack::NotFound
|
72
|
+
payload[:exist] = false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def url(key, expires_in:, disposition:, filename:, content_type:)
|
78
|
+
instrument :url, key: key do |payload|
|
79
|
+
expire_at = unix_timestamp_expires_at(expires_in)
|
80
|
+
generated_url = client.get_object_https_url(container,
|
81
|
+
key,
|
82
|
+
expire_at,
|
83
|
+
disposition: disposition,
|
84
|
+
filename: filename,
|
85
|
+
content_type: content_type)
|
86
|
+
payload[:url] = generated_url
|
87
|
+
|
88
|
+
generated_url
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
|
93
|
+
instrument :url, key: key do |payload|
|
94
|
+
expire_at = unix_timestamp_expires_at(expires_in)
|
95
|
+
generated_url = client.create_temp_url(container,
|
96
|
+
key,
|
97
|
+
expire_at,
|
98
|
+
'PUT',
|
99
|
+
port: 443,
|
100
|
+
scheme: "https",
|
101
|
+
content_type: content_type,
|
102
|
+
content_length: content_length,
|
103
|
+
etag: convert_base64digest_to_hexdigest(checksum))
|
104
|
+
|
105
|
+
payload[:url] = generated_url
|
106
|
+
|
107
|
+
generated_url
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def headers_for_direct_upload(key, content_type:, content_length:, checksum:)
|
112
|
+
{
|
113
|
+
'Content-Type' => content_type,
|
114
|
+
'Etag' => convert_base64digest_to_hexdigest(checksum),
|
115
|
+
'Content-Length' => content_length
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def object_for(key, &block)
|
122
|
+
client.get_object(container, key, &block)
|
123
|
+
end
|
124
|
+
|
125
|
+
# ActiveStorage sends a `Digest::MD5.base64digest` checksum
|
126
|
+
# OpenStack expects a `Digest::MD5.hexdigest` Etag
|
127
|
+
def convert_base64digest_to_hexdigest(base64digest)
|
128
|
+
base64digest.unpack('m0').first.unpack('H*').first if base64digest
|
129
|
+
end
|
130
|
+
|
131
|
+
def unix_timestamp_expires_at(seconds_from_now)
|
132
|
+
Time.current.advance(seconds: seconds_from_now).to_i
|
133
|
+
end
|
134
|
+
|
135
|
+
def format_range(range)
|
136
|
+
" bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}"
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activestorage-openstack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chedli Bourguiba
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-06-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fog-openstack
|
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: mime-types
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
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: sqlite3
|
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: rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 5.2.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 5.2.0
|
69
|
+
description: Wraps the OpenStack Swift/Storage service as an Active Storage service
|
70
|
+
email:
|
71
|
+
- bourguiba.chedli@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- MIT-LICENSE
|
77
|
+
- README.md
|
78
|
+
- Rakefile
|
79
|
+
- lib/active_storage/openstack.rb
|
80
|
+
- lib/active_storage/openstack/railtie.rb
|
81
|
+
- lib/active_storage/openstack/version.rb
|
82
|
+
- lib/active_storage/service/open_stack_service.rb
|
83
|
+
- lib/tasks/activestorage/openstack_tasks.rake
|
84
|
+
homepage: https://github.com/chaadow/activestorage-openstack
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 2.7.6
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: ActiveStorage wrapper for OpenStack Storage
|
108
|
+
test_files: []
|