openbanana 1.0.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.
- data/.gitignore +18 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +62 -0
- data/Rakefile +8 -0
- data/lib/openbanana.rb +101 -0
- data/lib/openbanana/tasks.rb +16 -0
- data/lib/openbanana/version.rb +3 -0
- data/openbanana.gemspec +20 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/tasks_spec.rb +131 -0
- metadata +80 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Lookout, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Open Banana
|
2
|
+
|
3
|
+
[](https://buildhive.cloudbees.com/job/lookout/job/openbanana/)
|
4
|
+
|
5
|
+
Openbanana is a gem that, currently, provides a `db:grant` rake task for Rails
|
6
|
+
projects.
|
7
|
+
|
8
|
+
What this `db:grant` task does is creates the database and sets up the initial grants for the database
|
9
|
+
configured in the `config/database.yml` file
|
10
|
+
|
11
|
+
To use Openbanana, include it in your `Rakefile`:
|
12
|
+
|
13
|
+
require 'openbanana/tasks'
|
14
|
+
|
15
|
+
And in your `Gemfile`:
|
16
|
+
|
17
|
+
gem "openbanana", "~> 0.2"
|
18
|
+
|
19
|
+
|
20
|
+
Make sure you have a source for either `maestro` or `dogwood` in your Gemfile.```
|
21
|
+
|
22
|
+
### Environment variables
|
23
|
+
|
24
|
+
* `DB_USER` overrides the default user (root) to grant privileges
|
25
|
+
* `DB_PASSWORD` overrides the default password (*empty*) to grant privileges
|
26
|
+
* `DB_HOST` overrides the hostname for the database server (defaults to
|
27
|
+
*localhost*)
|
28
|
+
|
29
|
+
|
30
|
+
For sharded configurations using a shards.yml file (such as using the octopus gem,
|
31
|
+
see https://github.com/tchandy/octopus) or with extra sharded entries in database.yml
|
32
|
+
(named *production* or *development*, etc.; such as using the data_fabric gem,
|
33
|
+
see https://github.com/bpot/data_fabric), adds a `db:grant_shards` task to create
|
34
|
+
and grant for a set of shard databases.
|
35
|
+
|
36
|
+
An example shard.yml looks like:
|
37
|
+
|
38
|
+
octopus:
|
39
|
+
...
|
40
|
+
production:
|
41
|
+
ungrouped_shard:
|
42
|
+
adapter: mysql2
|
43
|
+
database: foo
|
44
|
+
.... also specify username, password, host, etc.
|
45
|
+
shard_group:
|
46
|
+
shard1:
|
47
|
+
database: bar_1
|
48
|
+
....
|
49
|
+
shard2:
|
50
|
+
database: bar_2
|
51
|
+
....
|
52
|
+
...
|
53
|
+
|
54
|
+
or entries in database.yml that look like:
|
55
|
+
|
56
|
+
...
|
57
|
+
shard_1_production:
|
58
|
+
adapter: mysql2
|
59
|
+
database: foo_prod_s1
|
60
|
+
.. etc.
|
61
|
+
shard_2_production:
|
62
|
+
...
|
data/Rakefile
ADDED
data/lib/openbanana.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "openbanana/version"
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
module Openbanana
|
5
|
+
extend Rake::DSL
|
6
|
+
|
7
|
+
# Defining this just to make stubbing in rspec easier
|
8
|
+
def self.env
|
9
|
+
ENV
|
10
|
+
end
|
11
|
+
|
12
|
+
# load config YML file
|
13
|
+
def self.load_yml(filename = 'database.yml')
|
14
|
+
YAML.load_file(File.join(Rails.root, 'config', filename))
|
15
|
+
end
|
16
|
+
|
17
|
+
# read config YML for environment
|
18
|
+
def self.config
|
19
|
+
config = Openbanana.load_yml
|
20
|
+
return config[Rails.env]
|
21
|
+
end
|
22
|
+
|
23
|
+
# read config for sharded case using octopus shards.yml
|
24
|
+
def self.shard_config
|
25
|
+
config = Openbanana.load_yml('shards.yml')
|
26
|
+
config = config['octopus'] if config.keys == ['octopus']
|
27
|
+
config = config[Rails.env]
|
28
|
+
config = config['shards'] if config.keys == ['shards']
|
29
|
+
return config
|
30
|
+
rescue Errno::ENOENT => e
|
31
|
+
puts 'No shards.yml, using shards in database.yml'
|
32
|
+
config = Openbanana.load_yml
|
33
|
+
return Hash[config.select {|k,v| k.include?(Rails.env) && k != Rails.env}]
|
34
|
+
end
|
35
|
+
|
36
|
+
# generate SQL statements for DB creation, permission grant
|
37
|
+
def self.grant_for(config)
|
38
|
+
grants = []
|
39
|
+
|
40
|
+
unless config['database']
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
|
44
|
+
grants << "CREATE DATABASE #{config['database']};"
|
45
|
+
|
46
|
+
if config['username']
|
47
|
+
identify_by = ''
|
48
|
+
if config['password']
|
49
|
+
identify_by = "IDENTIFIED BY '#{config['password']}'"
|
50
|
+
end
|
51
|
+
|
52
|
+
unless config['networks']
|
53
|
+
grants << "GRANT ALL PRIVILEGES ON #{config['database']}.* TO '#{config['username']}'@'%' #{identify_by};"
|
54
|
+
else
|
55
|
+
config['networks'].each do |network|
|
56
|
+
grants << "GRANT ALL PRIVILEGES ON #{config['database']}.* TO '#{config['username']}'@'#{network}' #{identify_by};"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
return grants
|
62
|
+
end
|
63
|
+
|
64
|
+
# run block on all contained hashes which have the key 'database'
|
65
|
+
def self.traverse(obj, &block)
|
66
|
+
case obj
|
67
|
+
when Hash
|
68
|
+
if obj['database']
|
69
|
+
block.call(obj)
|
70
|
+
else
|
71
|
+
obj.each {|k,v| traverse(v, &block)}
|
72
|
+
end
|
73
|
+
when Array
|
74
|
+
obj.each {|v| traverse(v, &block)}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# generate grants
|
79
|
+
def self.grants(args = {})
|
80
|
+
config = args[:sharded] ? Openbanana.shard_config : Openbanana.config
|
81
|
+
grants = []
|
82
|
+
Openbanana.traverse(config) do |leaf_config|
|
83
|
+
grants += Openbanana.grant_for(leaf_config)
|
84
|
+
end
|
85
|
+
return grants
|
86
|
+
end
|
87
|
+
|
88
|
+
# run task (here for DRY-ness)
|
89
|
+
def self.grants_task(args = {})
|
90
|
+
username = ENV['DB_USER'] || 'root'
|
91
|
+
password = ENV['DB_PASSWORD'] || ''
|
92
|
+
host = nil
|
93
|
+
if ENV['DB_HOST']
|
94
|
+
host = "--host=#{ENV['DB_HOST']}"
|
95
|
+
end
|
96
|
+
|
97
|
+
Openbanana.grants(args).each do |grant|
|
98
|
+
sh "mysql #{host} --user=#{username} --password=\"#{password}\" -e \"#{grant}\" || true"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
require 'openbanan'
|
5
|
+
|
6
|
+
namespace :db do
|
7
|
+
desc "Set up the appropriate user grants for this project based on config/database.yml"
|
8
|
+
task :grant do
|
9
|
+
Openbanana.grants_task
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Set up the appropriate user grants for this project based on config/shards.yml and shards in config/database.yml"
|
13
|
+
task :grant_shards do
|
14
|
+
Openbanana.grants_task(:sharded => true)
|
15
|
+
end
|
16
|
+
end
|
data/openbanana.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/openbanana/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["R. Tyler Croy"]
|
6
|
+
gem.email = ["tyler@monkeypox.org"]
|
7
|
+
gem.description = %q{Simple gem to handle creating DB grans}
|
8
|
+
gem.summary = %q{Simple gem to handle creating DB grans}
|
9
|
+
gem.homepage = "https://github.com/lookout/openbanana"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "openbanana"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Openbanana::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency 'rake'
|
19
|
+
gem.add_development_dependency 'rspec'
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rake"
|
2
|
+
|
3
|
+
shared_context "rake" do
|
4
|
+
let(:rake) { Rake::Application.new }
|
5
|
+
let(:task_name) { self.class.top_level_description }
|
6
|
+
let(:task_path) { File.expand_path("./lib/openbanana/tasks/#{task_name.split(":").first}.rake") }
|
7
|
+
subject { rake[task_name] }
|
8
|
+
|
9
|
+
before do
|
10
|
+
Rake.application = rake
|
11
|
+
Rake.application.rake_require(File.expand_path('./lib/openbanana/tasks'))
|
12
|
+
Rake::Task.define_task(:environment)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
|
17
|
+
require 'openbanana'
|
data/spec/tasks_spec.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'db:grant' do
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Openbanana do
|
8
|
+
before :each do
|
9
|
+
Rails = double('rails')
|
10
|
+
Rails.stub(:root).and_return('dummy_root')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#load_yml' do
|
14
|
+
it 'should load the database.yml file on Rails.root/config' do
|
15
|
+
YAML.should_receive(:load_file).with(Rails.root + '/config/database.yml').and_return({})
|
16
|
+
Openbanana.load_yml
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should load the shards.yml file on Rails.root/config' do
|
20
|
+
YAML.should_receive(:load_file).with(Rails.root + '/config/shards.yml').and_return({})
|
21
|
+
Openbanana.load_yml('shards.yml')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#config' do
|
26
|
+
let(:config) do
|
27
|
+
{ 'database' => 'test_db',
|
28
|
+
'username' => 'test_user',
|
29
|
+
'password' => 'test_password'}
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with development configuration' do
|
33
|
+
before :each do
|
34
|
+
Openbanana.should_receive(:load_yml).and_return({'development' => config})
|
35
|
+
Rails.stub(:env).and_return('development')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should return the proper configuration for this environment' do
|
39
|
+
result = Openbanana.config
|
40
|
+
result.should == config
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#shard_config' do
|
46
|
+
let(:config) do
|
47
|
+
{ 'database' => 'test_db',
|
48
|
+
'username' => 'test_user',
|
49
|
+
'password' => 'test_password'}
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with development configuration' do
|
53
|
+
before :each do
|
54
|
+
Openbanana.should_receive(:load_yml).and_return({'octopus' => {'development' => {'shards' => config}}})
|
55
|
+
Rails.stub(:env).and_return('development')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should return the proper configuration for this environment' do
|
59
|
+
result = Openbanana.shard_config
|
60
|
+
result.should == config
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#grants' do
|
66
|
+
before :each do
|
67
|
+
Openbanana.should_receive(:config).and_return(config)
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'in production' do
|
71
|
+
describe 'with networks' do
|
72
|
+
let(:config) do
|
73
|
+
{ 'database' => 'test_db',
|
74
|
+
'username' => 'test_user',
|
75
|
+
'password' => 'test_password',
|
76
|
+
'networks' => ['127.0.0.0/24']}
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should have networks' do
|
80
|
+
result = Openbanana.grants
|
81
|
+
result.should include("GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'127.0.0.0/24' IDENTIFIED BY 'test_password';")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'on shards' do
|
87
|
+
describe 'with multiple shards' do
|
88
|
+
let(:config) do
|
89
|
+
{
|
90
|
+
'shard1' => {
|
91
|
+
'database' => 'test_db1',
|
92
|
+
'username' => 'test_user',
|
93
|
+
'password' => 'test_password'
|
94
|
+
},
|
95
|
+
'shard2' => {
|
96
|
+
'database' => 'test_db2',
|
97
|
+
'username' => 'test_user',
|
98
|
+
'password' => 'test_password'
|
99
|
+
}
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should have both shards' do
|
104
|
+
result = Openbanana.grants
|
105
|
+
result.should include("GRANT ALL PRIVILEGES ON test_db1.* TO 'test_user'@'%' IDENTIFIED BY 'test_password';")
|
106
|
+
result.should include("GRANT ALL PRIVILEGES ON test_db2.* TO 'test_user'@'%' IDENTIFIED BY 'test_password';")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'grants should' do
|
112
|
+
let(:config) do
|
113
|
+
{ 'database' => 'test_db',
|
114
|
+
'username' => 'test_user',
|
115
|
+
'password' => 'test_password'}
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'generate a create database call' do
|
119
|
+
result = Openbanana.grants
|
120
|
+
result.should include('CREATE DATABASE test_db;')
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'generate a grant for the user on that database' do
|
124
|
+
result = Openbanana.grants
|
125
|
+
result.should include("GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'%' IDENTIFIED BY 'test_password';")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openbanana
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- R. Tyler Croy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &11245520 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *11245520
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &11245080 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *11245080
|
36
|
+
description: Simple gem to handle creating DB grans
|
37
|
+
email:
|
38
|
+
- tyler@monkeypox.org
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- LICENSE
|
46
|
+
- README.md
|
47
|
+
- Rakefile
|
48
|
+
- lib/openbanana.rb
|
49
|
+
- lib/openbanana/tasks.rb
|
50
|
+
- lib/openbanana/version.rb
|
51
|
+
- openbanana.gemspec
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
- spec/tasks_spec.rb
|
54
|
+
homepage: https://github.com/lookout/openbanana
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.10
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Simple gem to handle creating DB grans
|
78
|
+
test_files:
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
- spec/tasks_spec.rb
|