s3browser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a2af7ec1f09ccd3a5a9108b4db4cd02fff8d55bc
4
+ data.tar.gz: 37bc0b82fc54b2716711388437e688d32db12e06
5
+ SHA512:
6
+ metadata.gz: bfe118747868fdb3e74470a4b9d9551c97a988fc2efbb1f3b038d3c8604053384fb1df67e701b013a64d674605370acec46c53049463566e7d1bf2edbda4d664
7
+ data.tar.gz: 0b807d66b7fa7dc2f97cf2ba658d1dcb9a643c9c1cf0c91a6d965314032652c7548f93210a2fcbbdae7b26cbad6d5dc0e4c0e12cee016773f939a9a5273521e4
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .env
11
+ .vagrant
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in s3browser.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # S3Browser
2
+
3
+ The S3Browser is a simple wrapper around Amazon's [S3 Service](https://aws.amazon.com/s3/).
4
+ Apart from listing files and managing, S3 doesn't give you a lot of functionality.
5
+
6
+ This wrapper gives you a couple of killer functions:
7
+
8
+ * [x] Search
9
+ * [x] Sorting
10
+ * [x] Automatically update file information
11
+ * [x] Upload files
12
+ * [x] Download files
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 's3browser'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install s3browser
29
+
30
+ ## Usage
31
+
32
+ Here's an example config.ru for booting S3Browser::Server in your choice of Rack server:
33
+
34
+ ```ruby
35
+ # config.ru
36
+ require 's3browser/server'
37
+ run S3Browser::Server
38
+ ```
39
+
40
+ You can mount S3Browser to existing Rack (Sinatra) application as well:
41
+
42
+ ```ruby
43
+ # config.ru
44
+ require 'your_app'
45
+
46
+ require 's3browser/server'
47
+ run Rack::URLMap.new('/' => Sinatra::Application, '/s3browser' => S3Browser::Server)
48
+ ```
49
+
50
+ To run S3Browser rake files, require the tasks file:
51
+
52
+ ```ruby
53
+ # Rakefile
54
+ require 's3browser/gem_tasks'
55
+ ```
56
+
57
+ Run the fetcher
58
+
59
+ ```bash
60
+ bundle exec rake s3browser:fetch
61
+ ```
62
+
63
+ Run the server
64
+
65
+ ```bash
66
+ bundle exec rake s3browser:server
67
+ ```
68
+
69
+ Run the worker
70
+ ```
71
+ bundle exec s3browser-worker
72
+ ```
73
+
74
+ This will use the default config file `shoryuken-config.yml` generated by the setup process. You can override this and add any shoryuken options you want:
75
+
76
+ ```
77
+ bundle exec s3browser-worker -C config.yml -L /var/log/shoryuken.log -P ./tmp/shoryuken.pid
78
+ ```
79
+
80
+ ## Real time updates
81
+
82
+ S3 buckets can be configured to send [Event Notifications](http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html)
83
+ when certain events happen in a bucket.
84
+
85
+ ### Setup
86
+
87
+ Run `bundle exec rake s3browser:setup` to ensure the correct ENV variables are set, and that your AWS setup is correct.
88
+
89
+ It will:
90
+
91
+ 1. Record the neccesary ENV variables:
92
+ * AWS_ACCESS_KEY_ID
93
+ * AWS_SECRET_ACCESS_KEY
94
+ * AWS_REGION
95
+ * AWS_S3_BUCKET
96
+ * AWS_SQS_QUEUE
97
+ 2. Create the SQS queue, with the correct permissions
98
+ 3. Create the S3 bucket, with the correct notification configuration
99
+
100
+ To do the setup, the IAM profile you're using to run the script should have the following policy in place:
101
+
102
+ ```javascript
103
+ {
104
+ "Version": "2012-10-17",
105
+ "Statement": [
106
+ {
107
+ "Sid": "S3BrowserFullAccess",
108
+ "Effect": "Allow",
109
+ "Action": [
110
+ "s3:GetObject",
111
+ "s3:GetObjectVersion",
112
+ "s3:ListBucket",
113
+ "s3:PutObject",
114
+ "s3:CreateBucket",
115
+ "s3:PutBucketNotification"
116
+ ],
117
+ "Resource": [
118
+ "arn:aws:s3:::*",
119
+ "arn:aws:s3:::*/*"
120
+ ]
121
+ },
122
+ {
123
+ "Sid": "Stmt1460660107000",
124
+ "Effect": "Allow",
125
+ "Action": [
126
+ "sqs:DeleteMessage",
127
+ "sqs:ReceiveMessage",
128
+ "sqs:CreateQueue",
129
+ "sqs:GetQueueUrl",
130
+ "sqs:GetQueueAttributes",
131
+ "sqs:SetQueueAttributes"
132
+ ],
133
+ "Resource": [
134
+ "arn:aws:sqs:*"
135
+ ]
136
+ }
137
+ ]
138
+ }
139
+ ```
140
+
141
+ After setting up the queue and the bucket, a policy **without** the following actions can be used:
142
+
143
+ * s3:CreateBucket
144
+ * s3:PutBucketNotification
145
+ * sqs:CreateQueue
146
+ * sqs:GetQueueUrl
147
+ * sqs:GetQueueAttributes
148
+ * sqs:SetQueueAttributes
149
+
150
+ ## Development
151
+
152
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
153
+
154
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
155
+
156
+ ## Contributing
157
+
158
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jrgns/s3browser.
159
+
160
+
161
+ ## License
162
+
163
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
164
+
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/gem_tasks'
2
+ require 's3browser/gem_tasks'
3
+ task :default => :spec
data/Vagrantfile ADDED
@@ -0,0 +1,53 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure(2) do |config|
5
+ config.vm.box = "ubuntu/trusty64"
6
+
7
+ config.vm.network "forwarded_port", guest: 9200, host: 9200
8
+ config.vm.network "forwarded_port", guest: 9292, host: 9292
9
+
10
+ config.vm.provider "virtualbox" do |vb|
11
+ # Customize the amount of memory on the VM:
12
+ vb.memory = "2048"
13
+ end
14
+
15
+ config.vm.provision "shell", privileged: false, inline: <<-SHELL
16
+ # Repositories
17
+ wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
18
+ echo "deb http://packages.elastic.co/elasticsearch/2.x/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-2.x.list
19
+ sudo add-apt-repository ppa:webupd8team/java
20
+ sudo apt-get update
21
+ sudo apt-get upgrade -y
22
+
23
+ # Java
24
+ echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections
25
+ echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections
26
+ sudo apt-get install -y oracle-java8-installer
27
+
28
+ # Elasticsearch
29
+ sudo apt-get install -y elasticsearch
30
+ sudo service elasticsearch stop
31
+ echo "ES_HEAP_SIZE=1g" | sudo tee -a /etc/default/elasticsearch
32
+
33
+ # Dependencies / Utilities
34
+ sudo apt-get install -y screen curl git build-essential
35
+
36
+ # Ruby
37
+ if [ ! -f /home/vagrant/.rvm/scripts/rvm ]
38
+ then
39
+ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
40
+ \\curl -sSL https://get.rvm.io | bash
41
+ fi
42
+ source /home/vagrant/.rvm/scripts/rvm
43
+
44
+ # Gems
45
+ cd /vagrant
46
+ rvm use $(cat .ruby-version) --install
47
+ gem install bundler --no-rdoc --no-ri
48
+ bundle install
49
+
50
+ # Services
51
+ sudo service elasticsearch start
52
+ SHELL
53
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "s3browser"
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
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+ bundle exec rake s3browser:setup
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'shoryuken/cli'
5
+ require 's3browser/worker'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'shoryuken/cli'
9
+ require 's3browser/worker'
10
+ end
11
+
12
+ unless ARGV.include?('-C')
13
+ ARGV << '-C'
14
+ ARGV << 'shoryuken-config.yml'
15
+ end
16
+
17
+ # This comes from the shoryuken CLI
18
+ begin
19
+ Shoryuken::CLI.instance.run(ARGV)
20
+ rescue => e
21
+ raise e if $DEBUG
22
+ STDERR.puts e.message
23
+ STDERR.puts e.backtrace.join("\n")
24
+ exit 1
25
+ end
data/lib/s3browser.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "s3browser/version"
2
+
3
+ module S3Browser
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,43 @@
1
+ require 'aws-sdk'
2
+ require 'time'
3
+ require 's3browser/store'
4
+
5
+ module S3Browser
6
+ class Fetch
7
+ class Store < S3Browser::Store
8
+ plugin :es
9
+ plugin :images
10
+ end
11
+
12
+ def run
13
+ s3.list_objects(bucket: bucket).contents.map do |object|
14
+ info = s3.head_object({
15
+ bucket: bucket,
16
+ key: object.key
17
+ })
18
+
19
+ info = info.to_h.merge(object.to_h)
20
+ store.add bucket, info
21
+ end
22
+ end
23
+
24
+ private
25
+ def bucket
26
+ @bucket ||= ENV['AWS_S3_BUCKET']
27
+ end
28
+
29
+ private
30
+ def s3
31
+ @s3 ||= Aws::S3::Client.new
32
+ end
33
+
34
+ private
35
+ def store
36
+ @store ||= Store.new('s3browser')
37
+ end
38
+ end
39
+ end
40
+
41
+ if $0 == __FILE__
42
+ S3Browser::Fetch.new.run
43
+ end
@@ -0,0 +1,158 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 's3browser'
4
+ require 'yaml'
5
+
6
+ module S3Browser
7
+ class GemTasks < ::Rake::TaskLib
8
+ include ::Rake::DSL if defined?(::Rake::DSL)
9
+
10
+ def install_tasks
11
+ require 'dotenv/tasks'
12
+
13
+ namespace :s3browser do
14
+ desc 'Run the web server for S3Browser'
15
+ task :server do
16
+ require 's3browser/server'
17
+ app = S3Browser::Server
18
+ app.set :environment, :production
19
+ app.set :bind, '0.0.0.0'
20
+ app.set :port, 9292
21
+ app.run!
22
+ end
23
+
24
+ desc 'Fetch and store all the S3 objects'
25
+ task :fetch do
26
+ require 's3browser/fetch'
27
+ S3Browser::Fetch.new.run
28
+ end
29
+
30
+ desc 'Set up the S3Browser'
31
+ task :setup => :dotenv do
32
+ require 'highline'
33
+ require 'json'
34
+ require 'aws-sdk'
35
+ require 'time'
36
+ require 'logger'
37
+ # Aws.config.update(logger: Logger.new($stdout), log_level: :debug, log_formatter: Aws::Log::Formatter.colored)
38
+
39
+
40
+ if File.exist?('.env') == false || cli.agree('Do you want to update your .env file (y/n)?') { |q| q.default = 'n' }
41
+ setup_env
42
+ end
43
+
44
+ if cli.agree('Should we set up SQS notification on the S3 bucket for you (y/n)?') { |q| q.default = 'y' }
45
+ setup_bucket
46
+ setup_sqs
47
+ end
48
+
49
+ if cli.agree('Do you want to generate a Shoryuken worker config (y/n)?') { |q| q.default = 'y' }
50
+ setup_worker_config
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def setup_env
57
+ envs = {}
58
+ envs[:AWS_ACCESS_KEY_ID] = cli.ask('What is your AWS Access Key ID') { |q| q.validate = /^\w+$/; q.default = ENV['AWS_ACCESS_KEY_ID'] if ENV['AWS_ACCESS_KEY_ID'] }
59
+ envs[:AWS_SECRET_ACCESS_KEY] = cli.ask('What is your AWS Secret Access Key') { |q| q.validate = /^[\w\/\+]+$/; q.default = ENV['AWS_SECRET_ACCESS_KEY'] if ENV['AWS_SECRET_ACCESS_KEY'] }
60
+ envs[:AWS_REGION] = cli.ask('What AWS region should the service be located in') { |q| q.validate = /^[a-z]{2}\-[a-z]+\-\d$/; q.default = ENV['AWS_REGION'] if ENV['AWS_REGION'] }
61
+ envs[:AWS_S3_BUCKET] = cli.ask('What is the name of the S3 bucket to use') { |q| q.validate = /^[^ ]+$/; ; q.default = ENV['AWS_S3_BUCKET'] if ENV['AWS_S3_BUCKET'] }
62
+ envs[:AWS_SQS_QUEUE] = cli.ask('What is the name of the SQS queue to use') { |q| q.validate = /^[^ ]+$/; ; q.default = ENV['AWS_SQS_QUEUE'] if ENV['AWS_SQS_QUEUE'] }
63
+
64
+ envs_string = envs.map {|k,v| "#{k}=#{v}"}.join("\n") + "\n"
65
+
66
+ cli.say 'This is the proposed .env file:'
67
+ cli.say envs_string + "\n"
68
+
69
+ write_file = cli.agree 'Are you happy with the settings (y/n)? If yes, your current .env file will be overwritten'
70
+
71
+ if write_file
72
+ cli.say 'Writing .env file'
73
+ File.open('.env', 'w') { |file| file.write('# export $(cat .env | grep -v ^# | xargs)' + "\n" + envs_string) }
74
+ Dotenv.load! # Reload the .env files
75
+ else
76
+ cli.say 'Skipping the .env file'
77
+ end
78
+ end
79
+
80
+ def setup_bucket
81
+ # Ensure that the bucket exists
82
+ s3.create_bucket({
83
+ bucket: ENV['AWS_S3_BUCKET']
84
+ })
85
+ cli.say "Created the S3 bucket: #{ENV['AWS_S3_BUCKET']}"
86
+ rescue
87
+ cli.say "Bucket already exists: #{ENV['AWS_S3_BUCKET']}"
88
+ end
89
+
90
+ def setup_sqs
91
+ # Create the Queue
92
+ resp = sqs.create_queue(
93
+ queue_name: ENV['AWS_SQS_QUEUE']
94
+ )
95
+ queue_url = resp.to_h[:queue_url]
96
+ cli.say "Created queue: #{queue_url}"
97
+
98
+ # Replace the access policy on the queue to allow the bucket to write to it
99
+ queue_arn = sqs.get_queue_attributes(queue_url: queue_url, attribute_names: ['QueueArn']).attributes['QueueArn']
100
+ sqs.set_queue_attributes(
101
+ queue_url: queue_url,
102
+ attributes: {
103
+ 'Policy' => sqs_policy(ENV['AWS_S3_BUCKET'], queue_arn)
104
+ }
105
+ )
106
+ cli.say 'Created the correct queue policy'
107
+
108
+ # Ensure that the bucket pushes notifications to the queue
109
+ s3.put_bucket_notification_configuration({
110
+ bucket: ENV['AWS_S3_BUCKET'],
111
+ notification_configuration: {
112
+ queue_configurations: [
113
+ {
114
+ id: "S3BrowserNotification",
115
+ queue_arn: queue_arn,
116
+ events: ['s3:ObjectCreated:*','s3:ObjectRemoved:*']
117
+ }
118
+ ]
119
+ }
120
+ })
121
+ cli.say 'Set the bucket to push notifications to SQS'
122
+ end
123
+
124
+ def setup_worker_config
125
+ config = {
126
+ 'concurrency': 1,
127
+ 'delay': 300,
128
+ 'queues': [ ENV['AWS_SQS_QUEUE'] ]
129
+ }
130
+
131
+ cli.say 'Writing shoryuken-config.yml'
132
+ File.open('shoryuken-config.yml', 'w') { |file| file.write(config.to_yaml) }
133
+ end
134
+
135
+ def sqs
136
+ @sqs ||= Aws::SQS::Client.new
137
+ end
138
+
139
+ def s3
140
+ @s3 ||= Aws::S3::Client.new
141
+ end
142
+
143
+ def cli
144
+ @cli ||= HighLine.new
145
+ end
146
+
147
+ def sqs_policy(bucket_name, queue_arn)
148
+ folder = File.expand_path File.dirname(__FILE__)
149
+ policy = JSON.parse(File.read("#{folder}/policy.json"))
150
+ policy['Id'] = Time.now.strftime('%Y%m%dT%H%M%S')
151
+ policy['Statement'][0]['Condition']['ArnLike']['aws:SourceArn'] = "arn:aws:s3:*:*:#{bucket_name}"
152
+ policy['Statement'][0]['Resource'] = queue_arn
153
+ JSON.generate(policy)
154
+ end
155
+ end
156
+ end
157
+
158
+ S3Browser::GemTasks.new.install_tasks