activestorage-openstack-shamox 0.7.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4d91e85cc650d641f99bdec4ec336e024171e41ccde924e1a31a99a121813e18
4
+ data.tar.gz: c97143273ac456414917b7e7a1a5d3782d479430904ddf27b874e2b475b1d4f5
5
+ SHA512:
6
+ metadata.gz: 872ec15aaa51d44a55ee894bd1f92d0e4d80c74408340a0c700eb68cfebc93ce8c655080c3556341ca41f58fd75d456ddf654919f74fc5fea9da0dd2c3e51460
7
+ data.tar.gz: 8f5d505ddb16b08166eb2f81c4920b5fb03f3c52222a1814eb630ad514ed86895ed97cccba9a19b15fc997185c1b55f52194ff57fa16d6525a3c23095de6d36e
@@ -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.
@@ -0,0 +1,161 @@
1
+ # ActiveStorage::Openstack
2
+ This rails plugin wraps the OpenStack Swift provider as an Active Storage service.
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/activestorage-openstack.svg)](https://badge.fury.io/rb/activestorage-openstack)
5
+ [![Build Status](https://travis-ci.com/ShamoX/activestorage-openstack.svg?branch=master)](https://travis-ci.com/ShamoX/activestorage-openstack)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/567a1c8e09288db91781/maintainability)](https://codeclimate.com/github/ShamoX/activestorage-openstack/maintainability)
7
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/567a1c8e09288db91781/test_coverage)](https://codeclimate.com/github/ShamoX/activestorage-openstack/test_coverage)
8
+
9
+
10
+ # PLEASE FORGIVE ME
11
+ Few monthes ago, I tried to contact `chaadow` - which seems to be the new maintainer
12
+ of this project - and got no answer. Since I needed updates on this gem and no ones
13
+ seemed to take it back, I decided to create and setup this new version.
14
+
15
+ For now I call it `activestorage-openstack-shamox`, just because I can't take over
16
+ `activestorage-openstack` from rubygem without a consent of its owner.
17
+
18
+ ## Installation
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'activestorage-openstack-shamox'
23
+ ```
24
+
25
+ And then execute:
26
+ ```bash
27
+ $ bundle
28
+ ```
29
+
30
+ Or install it yourself as:
31
+ ```bash
32
+ $ gem install activestorage-openstack-shamox
33
+ ```
34
+
35
+ ## Usage
36
+ in `config/storage.yml`, in your Rails app, create an entry with the following keys:
37
+ ```yaml
38
+ dev_openstack:
39
+ service: OpenStack
40
+ container: <container name> # Container name for your OpenStack provider
41
+ credentials:
42
+ openstack_auth_url: <auth url>
43
+ openstack_username: <username>
44
+ openstack_api_key: <password>
45
+ openstack_project_id: <region>
46
+ openstack_region: <region>
47
+ openstack_temp_url_key: <temp url key> # Mandatory, instructions below
48
+ connection_options: # optional
49
+ chunk_size: 2097152 # 2MBs - 1MB is the default
50
+ ```
51
+
52
+ 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.
53
+
54
+ Then register the provider in your `config/{environment}.rb` (`config/development.rb`/`config/test.rb`/`config/production.rb`)
55
+
56
+ For example, for the `dev_openstack` entry above, change the `config` variable in `config/development.rb` like the following:
57
+ ```ruby
58
+ # Store uploaded files on the local file system (see config/storage.yml for options)
59
+ config.active_storage.service = :dev_openstack
60
+ ```
61
+
62
+ ## Migrating from fog-openstack `0.1.x` to `0.2.x`
63
+
64
+ 1- From your configuration file (`config/storage.yml`) change the `openstack_auth_uri` from :
65
+ ```yaml
66
+ openstack_auth_url: https://auth.example.com/v2.0/tokens
67
+ ```
68
+ to :
69
+ ```yaml
70
+ openstack_auth_url: https://auth.example.com
71
+ ```
72
+ ==> **specifying the version in the `openstack_auth_url` key would break things**
73
+
74
+ 2- Second, specify the Keystone version (default is `v3.0`, however it is retro-compatible with v2.0 (So for now, adding this key won't affect the normal functioning of this gem, but is highly recommended)
75
+ - *Additionally v2.0 is deprecated.*
76
+ ```yaml
77
+ openstack_identity_api_version: v2.0
78
+ ```
79
+
80
+ For further informations, please refer to [fog-openstack's README](https://github.com/fog/fog-openstack/)
81
+
82
+ ## Setting up a container
83
+
84
+ From your OpenStack provider website, create or sign in to your account.
85
+ Then from your dashboard, create a container, and save the configuration generated.
86
+
87
+ It is a good practice to create a separate container for each of your environments.
88
+ Once safely saved, you can add them to your storage configuration in your Rails application.
89
+ ## `temp_url_key` configuration
90
+
91
+ 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).
92
+
93
+ To create it and post it you can use `bin/create_and_post_tempurl_key.sh` after having set your environment.
94
+ To set your environment set :
95
+ ```shell
96
+ export OS_AUTH_URL "https://auth.cloud.ovh.net"
97
+ export OS_IDENTITY_API_VERSION "3"
98
+
99
+ export OS_PROJECT_ID="your project id"
100
+
101
+ # In addition to the owning entity (tenant), openstack stores the entity
102
+ # performing the action as the **user**.
103
+ export OS_USERNAME="your username"
104
+
105
+ # With Keystone you pass the keystone password.
106
+ export OS_PASSWORD="your secret passwor"
107
+
108
+ # If your configuration has multiple regions, we set that information here.
109
+ # OS_REGION_NAME is optional and only valid in certain environments.
110
+ export OS_REGION_NAME="BHS1"
111
+ ```
112
+
113
+ To setup travis tests, you need to set `OPENSTACK_TEMP_URL_KEY`.
114
+
115
+ ## `ActiveStorage::Openstack`'s Content-Type handling
116
+
117
+ OpenStack Swift handles the Content-Type of an object differently from other object storage services. You cannot overwrite the Content-Type via a temp URL. This gem will try very hard to set the right Content-Type for an object at object creation (either via server upload or direct upload) but this is wrong in some edge cases (e.g. you use direct upload and the browser provides a wrong mime type).
118
+
119
+ For these edge cases `ActiveStorage::Blob::Identifiable` downloads the first 4K of a file, identifies the content type and saves the result in the database. For `ActiveStorage::Openstack` we also need to update the Content-Type of the object. This is done automatically with a little monkey patch.
120
+
121
+ ## Testing
122
+ First, run `bundle` to install the gem dependencies (both development and production)
123
+ ```shell
124
+ $ bundle
125
+ ```
126
+ Then, from the root of the plugin, copy the following file and fill in the appropriate credentials.
127
+ **Preferably, set up a container for your testing, separate from production.**
128
+ ```shell
129
+ $ cp test/configurations.example.yml test/configurations.yml
130
+ $ source ./bin/openrc.sh
131
+ ```
132
+ And then run the tests:
133
+ ```shell
134
+ $ bin/test
135
+ ```
136
+
137
+ ## Contributions
138
+ 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/ShamoX/activestorage-openstack/issues
139
+
140
+ I use the git flow scheme then, when wanting to merge, please target the `develop`
141
+ branch and not the `master`. I would recommand you to use `git flow` also, and
142
+ use the following configuration (which is the default):
143
+ ```
144
+ $ git flow init
145
+ Which branch should be used for bringing forth production releases?
146
+ - master
147
+ Branch name for production releases: [master]
148
+ Branch name for "next release" development: [develop]
149
+
150
+ How to name your supporting branch prefixes?
151
+ Feature branches? [feature/]
152
+ Bugfix branches? [bugfix/]
153
+ Release branches? [release/]
154
+ Hotfix branches? [hotfix/]
155
+ Support branches? [support/]
156
+ Version tag prefix? []
157
+ Hooks and filters directory? [/home/rlaures/dev/activestorage-openstack/.git/hooks]
158
+ ```
159
+
160
+ ## License
161
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -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,6 @@
1
+ module ActiveStorage
2
+ module Openstack
3
+ class Railtie < ::Rails::Railtie
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveStorage
2
+ module Openstack
3
+ VERSION = '0.7.0-alpha'
4
+ end
5
+ end
@@ -0,0 +1,146 @@
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 =
9
+ if connection_options.present?
10
+ credentials.reverse_merge(connection_options: connection_options)
11
+ else
12
+ credentials
13
+ end
14
+
15
+ @client = Fog::OpenStack::Storage.new(settings)
16
+ @container = Fog::OpenStack.escape(container)
17
+ end
18
+
19
+ def upload(key, io, checksum: nil, **)
20
+ instrument :upload, key: key, checksum: checksum do
21
+ params = {}.merge(etag: convert_base64digest_to_hexdigest(checksum))
22
+ begin
23
+ client.put_object(container, key, io, params)
24
+ rescue Excon::Error::UnprocessableEntity
25
+ raise ActiveStorage::IntegrityError
26
+ end
27
+ end
28
+ end
29
+
30
+ def download(key, &block)
31
+ if block_given?
32
+ instrument :streaming_download, key: key do
33
+ object_for(key, &block).body
34
+ end
35
+ else
36
+ instrument :download, key: key do
37
+ object_for(key).body
38
+ end
39
+ end
40
+ end
41
+
42
+ def download_chunk(key, range)
43
+ instrument :download_chunk, key: key, range: range do
44
+ object_for(key).body[range]
45
+ end
46
+ end
47
+
48
+ def delete(key)
49
+ instrument :delete, key: key do
50
+ begin
51
+ client.delete_object(container, key)
52
+ rescue Fog::OpenStack::Storage::NotFound
53
+ false
54
+ end
55
+ end
56
+ end
57
+
58
+ def delete_prefixed(prefix)
59
+ instrument :delete, prefix: prefix do
60
+ directory = client.directories.get(container)
61
+ filtered_files = client.files(directory: directory, prefix: prefix)
62
+ filtered_files = filtered_files.map(&:key)
63
+
64
+ client.delete_multiple_objects(container, filtered_files)
65
+ end
66
+ end
67
+
68
+ def exist?(key)
69
+ instrument :exist, key: key do |payload|
70
+ begin
71
+ answer = object_for(key)
72
+ payload[:exist] = answer
73
+ rescue Fog::OpenStack::Storage::NotFound
74
+ payload[:exist] = false
75
+ end
76
+ end
77
+ end
78
+
79
+ def url(key, expires_in:, disposition:, filename:, content_type:)
80
+ instrument :url, key: key do |payload|
81
+ expire_at = unix_timestamp_expires_at(expires_in)
82
+ generated_url =
83
+ client.get_object_https_url(
84
+ container,
85
+ key,
86
+ expire_at,
87
+ disposition: disposition,
88
+ filename: filename,
89
+ content_type: content_type
90
+ )
91
+
92
+ payload[:url] = generated_url
93
+ generated_url
94
+ end
95
+ end
96
+
97
+ def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
98
+ instrument :url, key: key do |payload|
99
+ expire_at = unix_timestamp_expires_at(expires_in)
100
+
101
+ generated_url =
102
+ client.create_temp_url(
103
+ container,
104
+ key,
105
+ expire_at,
106
+ 'PUT',
107
+ port: 443,
108
+ scheme: "https",
109
+ content_type: content_type,
110
+ content_length: content_length,
111
+ etag: convert_base64digest_to_hexdigest(checksum)
112
+ )
113
+
114
+ payload[:url] = generated_url
115
+ generated_url
116
+ end
117
+ end
118
+
119
+ def headers_for_direct_upload(key, content_type:, content_length:, checksum:)
120
+ {
121
+ 'Content-Type' => content_type,
122
+ 'Etag' => convert_base64digest_to_hexdigest(checksum),
123
+ 'Content-Length' => content_length,
124
+ }
125
+ end
126
+
127
+ private
128
+ def object_for(key, &block)
129
+ client.get_object(container, key, &block)
130
+ end
131
+
132
+ # ActiveStorage sends a `Digest::MD5.base64digest` checksum
133
+ # OpenStack expects a `Digest::MD5.hexdigest` Etag
134
+ def convert_base64digest_to_hexdigest(base64digest)
135
+ base64digest.unpack('m0').first.unpack('H*').first if base64digest
136
+ end
137
+
138
+ def unix_timestamp_expires_at(seconds_from_now)
139
+ Time.current.advance(seconds: seconds_from_now).to_i
140
+ end
141
+
142
+ def format_range(range)
143
+ " bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}"
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,2 @@
1
+ require "active_storage/openstack/version"
2
+ require "active_storage/openstack/railtie"
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :activestorage_openstack do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activestorage-openstack-shamox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.0.pre.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Chedli Bourguiba
8
+ - Roland Laurès
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-10-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog-openstack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: mime-types
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: sqlite3
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rails
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 5.2.0
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 5.2.0
70
+ - !ruby/object:Gem::Dependency
71
+ name: simplecov
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: simplecov-console
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ description: Wraps the OpenStack Swift/Storage service as an Active Storage service
99
+ email:
100
+ - bourguiba.chedli@gmail.com
101
+ - roland@rlaures.pro
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - MIT-LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - lib/active_storage/openstack/railtie.rb
110
+ - lib/active_storage/openstack/version.rb
111
+ - lib/active_storage/service/open_stack_service.rb
112
+ - lib/activestorage-openstack.rb
113
+ - lib/tasks/activestorage/openstack_tasks.rake
114
+ homepage: https://github.com/shamox/activestorage-openstack
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: 2.2.2
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 1.8.11
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.7.6.2
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: ActiveStorage wrapper for OpenStack Storage (ShamoX version)
138
+ test_files: []