brillo 1.0.0 → 1.1.0

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
  SHA1:
3
- metadata.gz: b684f9b150cde1eded3db5ae684ca02853e6ae37
4
- data.tar.gz: 1a052b7afc30957c7b87b04506be442c511b65ea
3
+ metadata.gz: b1b61984d544d65ece11ac029344d31a7d3bc111
4
+ data.tar.gz: 38187ebba9e25dda6be33418813e457a292cfb6f
5
5
  SHA512:
6
- metadata.gz: b1726eac1715f1fda25a19e35f77e82bdfe528378c83736ca194ff86c0a1d6bd57eb2d203d4583d8e0cef9e758209200b3d818d167e3533f13d013b1ca0f8fb9
7
- data.tar.gz: 2e9857f15ea8486806208bf64954b35eec1371fceb183b27803e828baf1d6726a718f350f50f91ffe6f23e230f80270d8529820db706dfd9a4f5f7ed62055fed
6
+ metadata.gz: 285e40acd59b6ebd01809c99d4c13285f36b6366022df3ed781c6d0e89198c7448ecd72ba9245bd54ffbe2c08dfb93dbcecacf88d600a4a231c4062421f00b9e
7
+ data.tar.gz: 4665c6cf7c9a59736a577e9db36f17725ca453328aba4486a20ef66bb20eada68407b13dc847b452558fa430d64b0d1a16228eecf97f09d8d618c14972a3190b
data/.travis.yml CHANGED
@@ -1,4 +1,13 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.5
4
- before_install: gem install bundler -v 1.10.6
3
+ - 2.3.1
4
+ cache: bundler
5
+ services:
6
+ - mysql
7
+
8
+ before_install:
9
+ - mysql -e "create database IF NOT EXISTS brillo_test;" -uroot
10
+
11
+ script:
12
+ - bundle exec rspec
13
+ - cd example_app; bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.1.0
4
+ **New**
5
+ - **BREAKING** Brillo used to support loading your credentials from a YAML file at `/etc/ec2_secure_env.yml`
6
+ but no longer does. It is now your responsibility to ensure the credentials are in the environment Brillo
7
+ runs in.
8
+ - Removed the dependency on the AWS Timkay CLI, instead using the AWS gem.
9
+ - Added support for configuring all S3 parameters in Ruby land
10
+
11
+ **Fixed**
12
+ - Fix mysql exec when no host specified
13
+ - Fix postgres exec when no host specified
14
+ - Fix postgres adapter reference
15
+
16
+
3
17
  ## 1.0.0
4
18
  First public Brillo version!
5
19
 
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
- [![Build Status](https://travis-ci.com/bessey/brillo.svg?token=z16y9ppDyNfaLAvjjHbK&branch=master)](https://travis-ci.com/bessey/brillo)
1
+ [![Build Status](https://travis-ci.org/bessey/brillo.svg?branch=master)](https://travis-ci.org/bessey/brillo)
2
+ [![Gem Version](https://badge.fury.io/rb/brillo.svg)](https://badge.fury.io/rb/brillo)
2
3
 
3
4
  # Brillo
4
5
 
@@ -62,7 +63,9 @@ obfuscations: #
62
63
  user.email: email
63
64
  ```
64
65
 
65
- In order to communicate with S3, Brillo expects `AWS_ACCESS_KEY` and `AWS_SECRET_KEY` to be set in the environment. It uses [Tim Kay's AWS cli](http://timkay.com/aws/) to communicate with AWS.
66
+ Brillo uses [the official aws-sdk](https://github.com/aws/aws-sdk-ruby) to communicate with S3. There [are a number of ways](https://github.com/aws/aws-sdk-ruby#configuration) to pass your S3 credentials, but the simplest is to set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` in your environment.
67
+
68
+ If you'd like to see the gem in use, check out the [/example_app](https://github.com/bessey/brillo/tree/master/example_app) directory.
66
69
 
67
70
  ### Loading a database in development
68
71
 
@@ -76,7 +79,7 @@ $ rake db:load
76
79
  $ cap staging db:load
77
80
  ```
78
81
 
79
- ### Adding scrub tactics and obfuscations
82
+ ## Advanced Configuration
80
83
 
81
84
  If the built in record selection tactics aren't enough for you, or you need a custom obfuscation strategy, you can add them via the initializer. They are available in the YAML config like any other strategy.
82
85
 
@@ -94,11 +97,14 @@ Brillo.configure do |config|
94
97
  config.add_obfuscation :phone_with_id, -> (field, instance) {
95
98
  (555_000_0000 + instance.id).to_s
96
99
  }
100
+
101
+ # In addition to setting your S3 credentials via env you can set them something like this
102
+ config.transfer_config.secret_access_key = Rails.application.secrets.secret_access_key
103
+ config.transfer_config.access_key_id = Rails.application.secrets.access_key_id
97
104
  end
98
105
 
99
106
  ```
100
107
 
101
108
  ## To Do
102
109
 
103
- - Support S3 transfer via the usual AWS CLI
104
110
  - Support alternative transfer mechanisms
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+ rescue LoadError
9
+ end
data/brillo.gemspec CHANGED
@@ -13,18 +13,21 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/bessey/brillo"
14
14
  spec.license = "MIT"
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|dummy)/}) }
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|example_app)/}) }
17
17
  spec.bindir = "exe"
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_runtime_dependency "rake", "~> 10.0"
22
- spec.add_runtime_dependency "capistrano", "~> 3.0"
23
- spec.add_runtime_dependency "polo", "~> 0.3"
21
+ spec.add_dependency "rake", "~> 10.0"
22
+ spec.add_dependency "capistrano", "~> 3.0"
23
+ spec.add_dependency "polo", "~> 0.3"
24
+ spec.add_dependency "aws-sdk", "~> 2.0"
25
+ spec.add_dependency "activerecord", ">= 3.2"
26
+ spec.add_dependency "activesupport", ">= 3.2"
24
27
 
25
- spec.add_development_dependency "rails", ">= 3.2"
26
- spec.add_development_dependency "rspec", "~> 3.4"
28
+ spec.add_development_dependency "rails", "4.2.5.1"
29
+ spec.add_development_dependency "mysql2"
30
+ spec.add_development_dependency "rspec-rails", "~> 3.4"
27
31
  spec.add_development_dependency "pry"
28
32
  spec.add_development_dependency "benchmark-ips"
29
- spec.add_development_dependency "geminabox"
30
33
  end
@@ -1,11 +1,13 @@
1
1
  name: my-app # Namespace the scrubbed file will occupy
2
2
  ## Optional configuration (with defaults shown)
3
- # compress: true # Enables gzip on scrub and ungzip on load
4
- # send_to_s3: true # Disable to skip sending to S3, useful for debugging
5
- # fetch_from_s3: true # Disable to skip fetching from S3, useful when you have an existing scrub in tmp/
3
+ # compress: true # Enables gzip on scrub and ungzip on load
6
4
  #
7
5
  # obfuscations:
8
- # user.name: name # Scrub table.field with scrubber (see Brillo::SCRUBBERS for choices)
6
+ # user.name: name # Scrub table.field with scrubber (see Brillo::SCRUBBERS for choices)
7
+ transfer:
8
+ # enabled: true # Disable to skip transferring to and from S3, running purely locally
9
+ # bucket: database-scrubs
10
+ # region: us-west-2 # Override to change the region to somewhere nearer you
9
11
  explore:
10
12
  user: # Name of ActiveRecord class in snake_case
11
13
  tactic: all # Scrubbing tactic to use (see Brillo:TACTICS for choices)
@@ -25,7 +25,9 @@ module Brillo
25
25
  end
26
26
 
27
27
  def load_command
28
- "mysql --host #{config[:host]} -u #{config[:username]} #{config[:password] ? "-p#{config[:password]}" : ""} #{config[:database]}"
28
+ host = config[:host] ? "--host #{config[:host]}" : ""
29
+ password = config[:password] ? "-p#{config[:password]}" : ""
30
+ "mysql #{host} -u #{config[:username]} #{password} #{config[:database]}"
29
31
  end
30
32
  end
31
33
  end
@@ -2,7 +2,9 @@ module Brillo
2
2
  module Adapter
3
3
  class Postgres < Base
4
4
  def load_command
5
- "psql --host #{config[:host]} -U #{config[:username]} #{config[:password] ? "-W#{config[:password]}" : ""} #{config[:database]}"
5
+ host = config[:host] ? "--host #{config[:host]}" : ""
6
+ password = config[:password] ? "-W#{config[:password]}" : ""
7
+ "psql #{host} -U #{config[:username]} #{password} #{config[:database]}"
6
8
  end
7
9
  end
8
10
  end
data/lib/brillo/config.rb CHANGED
@@ -1,18 +1,12 @@
1
1
  module Brillo
2
2
  class Config
3
- AWS_KEY_PATH = '/etc/ec2_secure_env.yml'
4
- S3_BUCKET = 'scrubbed_databases2'
5
- attr_reader :app_name, :compress, :obfuscations, :klass_association_map, :db, :send_to_s3, :fetch_from_s3,
6
- :aws_key_path, :s3_bucket
3
+ attr_reader :app_name, :compress, :obfuscations, :klass_association_map, :db, :transfer_config
7
4
 
8
5
  def initialize(options = {})
9
6
  @app_name = options.fetch("name")
10
7
  @klass_association_map = options["explore"] || {}
11
8
  @compress = options.fetch("compress", true)
12
- @fetch_from_s3 = options.fetch("fetch_from_s3", true)
13
- @send_to_s3 = options.fetch("send_to_s3", true)
14
- @aws_key_path = options.fetch("aws_key_path", AWS_KEY_PATH)
15
- @s3_bucket = options.fetch("s3_bucket", S3_BUCKET)
9
+ @transfer_config = Transferrer::Config.new(options.fetch("transfer", {}))
16
10
  @obfuscations = parse_obfuscations(options["obfuscations"] || {})
17
11
  rescue KeyError => e
18
12
  raise ConfigParseError, e
@@ -46,7 +40,7 @@ module Brillo
46
40
  "#{app_name}-scrubbed.dmp"
47
41
  end
48
42
 
49
- def remote_filename
43
+ def compressed_filename
50
44
  compress ? "#{dump_filename}.gz" : dump_filename
51
45
  end
52
46
 
@@ -54,15 +48,15 @@ module Brillo
54
48
  app_tmp + dump_filename
55
49
  end
56
50
 
57
- def remote_path
58
- app_tmp + remote_filename
51
+ def compressed_dump_path
52
+ app_tmp + compressed_filename
59
53
  end
60
54
 
61
55
  def db
62
56
  @db_config ||= ActiveRecord::Base.connection.instance_variable_get(:@config).dup
63
57
  end
64
58
 
65
- # TODO support other tranfer systems
59
+ # TODO support other transfer systems
66
60
  def transferrer
67
61
  Transferrer::S3.new(self)
68
62
  end
@@ -71,7 +65,7 @@ module Brillo
71
65
  case db[:adapter].to_sym
72
66
  when :mysql2
73
67
  Adapter::MySQL.new(db)
74
- when :postgres
68
+ when :postgresql
75
69
  Adapter::Postgres.new(db)
76
70
  else
77
71
  raise ConfigParseError, "Unsupported DB adapter #{db[:adapter]}"
@@ -14,7 +14,7 @@ module Brillo
14
14
  if success
15
15
  [success, stdout, stderr]
16
16
  else
17
- raise RuntimeError, stderr
17
+ raise RuntimeError, "#{stdout} #{stderr}"
18
18
  end
19
19
  end
20
20
 
data/lib/brillo/loader.rb CHANGED
@@ -7,7 +7,7 @@ module Brillo
7
7
  attr_reader :config
8
8
 
9
9
  def initialize(config)
10
- raise "⚠️ DON'T LOAD IN PRODUCTION! ⚠️" if Rails.env.production?
10
+ raise "⚠️ DON'T LOAD IN PRODUCTION! ⚠️" if production?
11
11
  @config = config
12
12
  end
13
13
 
@@ -26,7 +26,7 @@ module Brillo
26
26
 
27
27
  def import_sql
28
28
  if config.compress
29
- execute!("gunzip -c #{config.remote_path} | #{sql_load_command}")
29
+ execute!("gunzip -c #{config.compressed_dump_path} | #{sql_load_command}")
30
30
  else
31
31
  execute!("cat #{config.dump_path} | #{sql_load_command}")
32
32
  end
@@ -35,6 +35,10 @@ module Brillo
35
35
 
36
36
  private
37
37
 
38
+ def production?
39
+ (ENV['RAILS_ENV'] || ENV['RUBY_ENV']) == 'production'
40
+ end
41
+
38
42
  def sql_load_command
39
43
  config.adapter.load_command
40
44
  end
@@ -1,10 +1,12 @@
1
- module Brillo
2
- class Railtie < Rails::Railtie
3
- rake_tasks do
4
- load "tasks/brillo.rake"
5
- end
6
- generators do
7
- require "generators/brillo.rb"
1
+ if defined? Rails
2
+ module Brillo
3
+ class Railtie < Rails::Railtie
4
+ rake_tasks do
5
+ load "tasks/brillo.rake"
6
+ end
7
+ generators do
8
+ require "generators/brillo.rb"
9
+ end
8
10
  end
9
11
  end
10
12
  end
@@ -32,7 +32,7 @@ module Brillo
32
32
  end
33
33
 
34
34
  def scrub!
35
- FileUtils.rm [config.dump_path, config.remote_path], force: true
35
+ FileUtils.rm config.compressed_filename, force: true
36
36
  configure_polo
37
37
  adapter.dump_structure_and_migrations(config)
38
38
  explore_all_classes
@@ -0,0 +1,24 @@
1
+ module Brillo
2
+ module Transferrer
3
+ class Config
4
+ attr_accessor :bucket, :region, :enabled, :secret_access_key, :access_key_id
5
+ def initialize(bucket: 'database-scrubs', region: 'us-west-2', enabled: true)
6
+ @enabled = enabled
7
+ @bucket = bucket
8
+ @region = region
9
+ end
10
+
11
+ def region
12
+ @region || ENV['AWS_REGION']
13
+ end
14
+
15
+ def secret_access_key
16
+ @secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'] || ENV["AWS_SECRET_KEY"] || ENV["EC2_SECRET_KEY"]
17
+ end
18
+
19
+ def access_key_id
20
+ @access_key_id || ENV['AWS_ACCESS_KEY_ID'] || ENV["AWS_ACCESS_KEY"] || ENV["EC2_ACCESS_KEY"]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,65 +1,57 @@
1
+ require 'aws-sdk'
2
+
1
3
  module Brillo
2
4
  module Transferrer
3
5
  class S3
4
6
  include Helpers::ExecHelper
5
7
  include Logger
6
- attr_reader :credentials, :bucket, :remote_filename, :remote_path, :download_enabled, :upload_enabled
7
- attr_reader :key_path
8
+ attr_reader :bucket, :filename, :region, :path, :enabled
8
9
 
9
10
  def initialize(config)
10
- @download_enabled = config.fetch_from_s3
11
- @upload_enabled = config.send_to_s3
12
- @bucket = config.s3_bucket
13
- @key_path = config.aws_key_path
14
- @remote_filename = config.remote_filename
15
- @remote_path = config.remote_path
16
- load_credentials
11
+ @enabled = config.transfer_config.enabled
12
+ @bucket = config.transfer_config.bucket
13
+ @region = config.transfer_config.region
14
+ @filename = config.compressed_filename
15
+ @path = config.compressed_dump_path
16
+ Aws.config.update(
17
+ credentials: Aws::Credentials.new(
18
+ config.transfer_config.access_key_id,
19
+ config.transfer_config.secret_access_key
20
+ ),
21
+ region: config.transfer_config.region
22
+ )
17
23
  end
18
24
 
19
25
  def download
20
- return unless download_enabled
21
- load_credentials
22
- FileUtils.rm [config.dump_path, config.remote_path], force: true
23
- aws_s3 "get"
26
+ return unless enabled
27
+ FileUtils.rm path, force: true
28
+ client.get_object({bucket: bucket, key: path.to_s}, target: path)
29
+ rescue Aws::S3::Errors::NoSuchBucket
30
+ create_bucket
31
+ retry
24
32
  end
25
33
 
26
34
  def upload
27
- return unless upload_enabled
28
- load_credentials
29
- aws_s3 "put"
35
+ return unless enabled
36
+ object = resource.bucket(bucket).object(path.to_s)
37
+ object.upload_file(path)
38
+ rescue Aws::S3::Errors::NoSuchBucket
39
+ create_bucket
40
+ retry
30
41
  end
31
42
 
32
43
  private
33
44
 
34
- def load_credentials
35
- if File.exist?(key_path)
36
- @credentials = YAML.load_file(key_path)
37
- else
38
- key = ENV["AWS_SECRET_KEY"] || ENV["EC2_SECRET_KEY"]
39
- unless key && key.length > 10
40
- raise CredentialsError, "AWS credentials not found. Expected AWS_ACCESS_KEY and AWS_SECRET_KEY to be set!"
41
- end
42
- @credentials = {
43
- 'aws_access_key' => ENV["AWS_ACCESS_KEY"] || ENV["EC2_ACCESS_KEY"],
44
- 'aws_secret_key' => key
45
- }
46
- end
47
- end
48
-
49
- def aws_s3 api_command
50
- execute!("#{aws_env} #{aws_bin} #{api_command} #{bucket}/#{remote_filename} #{remote_path}")
45
+ def create_bucket
46
+ client.create_bucket(bucket: bucket)
51
47
  end
52
48
 
53
- def aws_bin
54
- if File.exist?('/usr/local/bin/awstk')
55
- '/usr/local/bin/awstk'
56
- else
57
- '/usr/local/bin/aws'
58
- end
49
+ def client
50
+ Aws::S3::Client.new
59
51
  end
60
52
 
61
- def aws_env
62
- "EC2_ACCESS_KEY=#{credentials['aws_access_key']} EC2_SECRET_KEY=#{credentials['aws_secret_key']}"
53
+ def resource
54
+ Aws::S3::Resource.new
63
55
  end
64
56
  end
65
57
  end
@@ -1,3 +1,3 @@
1
1
  module Brillo
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
data/lib/brillo.rb CHANGED
@@ -1,3 +1,7 @@
1
+ require 'yaml'
2
+ require 'active_support'
3
+ require 'active_support/core_ext/string/inflections'
4
+ require 'active_record'
1
5
  require "brillo/version"
2
6
 
3
7
  require 'brillo/errors'
@@ -8,6 +12,7 @@ require 'brillo/adapter/base'
8
12
  require 'brillo/adapter/mysql'
9
13
  require 'brillo/adapter/postgres'
10
14
 
15
+ require 'brillo/transferrer/config'
11
16
  require 'brillo/transferrer/s3'
12
17
 
13
18
  require 'brillo/dumper/mysql_dumper'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brillo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Bessey
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-29 00:00:00.000000000 Z
11
+ date: 2016-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -53,13 +53,27 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.3'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rails
56
+ name: aws-sdk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
60
74
  - !ruby/object:Gem::Version
61
75
  version: '3.2'
62
- type: :development
76
+ type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
@@ -67,21 +81,35 @@ dependencies:
67
81
  - !ruby/object:Gem::Version
68
82
  version: '3.2'
69
83
  - !ruby/object:Gem::Dependency
70
- name: rspec
84
+ name: activesupport
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - "~>"
87
+ - - ">="
74
88
  - !ruby/object:Gem::Version
75
- version: '3.4'
89
+ version: '3.2'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '3.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 4.2.5.1
76
104
  type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
80
- - - "~>"
108
+ - - '='
81
109
  - !ruby/object:Gem::Version
82
- version: '3.4'
110
+ version: 4.2.5.1
83
111
  - !ruby/object:Gem::Dependency
84
- name: pry
112
+ name: mysql2
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
115
  - - ">="
@@ -95,7 +123,21 @@ dependencies:
95
123
  - !ruby/object:Gem::Version
96
124
  version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
- name: benchmark-ips
126
+ name: rspec-rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.4'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.4'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry
99
141
  requirement: !ruby/object:Gem::Requirement
100
142
  requirements:
101
143
  - - ">="
@@ -109,7 +151,7 @@ dependencies:
109
151
  - !ruby/object:Gem::Version
110
152
  version: '0'
111
153
  - !ruby/object:Gem::Dependency
112
- name: geminabox
154
+ name: benchmark-ips
113
155
  requirement: !ruby/object:Gem::Requirement
114
156
  requirements:
115
157
  - - ">="
@@ -155,6 +197,7 @@ files:
155
197
  - lib/brillo/logger.rb
156
198
  - lib/brillo/railtie.rb
157
199
  - lib/brillo/scrubber.rb
200
+ - lib/brillo/transferrer/config.rb
158
201
  - lib/brillo/transferrer/s3.rb
159
202
  - lib/brillo/validator.rb
160
203
  - lib/brillo/version.rb