shred 0.0.4 → 0.0.5

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: b2e054fbed6a3aea3fa024120dc4f04ab56b8d11
4
- data.tar.gz: fb5a6578711711182bce19418638681f09336a31
3
+ metadata.gz: d94a83bf54dff1959be163040d2703457f1b6777
4
+ data.tar.gz: 99aa30b2a973d733eb52c258dfd18dd3ff80a752
5
5
  SHA512:
6
- metadata.gz: 766546e3f1b2d13863dab3658da6809487569516f8c12319ede06c5e19473ee0dd8b57dee953fc2d327344f4b844882d5370dc6cd49dc02b35cc1ef40c4c477f
7
- data.tar.gz: 84d5c56ea550317e12c2d772cbf1b7ea744858dfb7bba05746d20d40ead486b329b530fdad88fe74c97f805f847cd8049b755f20f40f7ebb57de135adc48a50d
6
+ metadata.gz: 675abe608dbbdd741e6ec746cbb44a8c5236af20a7138b176fedebd8c1fb4b5ab639c07fccbe4bf257b1264d9f012168045ad3b90af9383a47d982b234c99252
7
+ data.tar.gz: 965952a420c451921659a40dd8739e8edac1fe931344f97e7c16853180109fd5818eb26477a10cbac289bd47d1fc0890de09cff2a3b352bd80a1bf90c7f49e86
@@ -167,6 +167,25 @@ module Shred
167
167
  value
168
168
  end
169
169
 
170
+ def interpolate_value(value, context: {})
171
+ value.gsub(/{[^}]+}/) do |match|
172
+ ref = match.slice(1, match.length)
173
+ ref = ref.slice(0, ref.length - 1)
174
+ if ref =~ /^env\:(.+)$/
175
+ env_key = $1.upcase
176
+ if ENV.key?(env_key)
177
+ ENV[env_key]
178
+ else
179
+ raise "Unset environment variable '#{env_key}' referenced by value '#{value}'"
180
+ end
181
+ elsif context.key?(ref.to_sym)
182
+ context[ref.to_sym]
183
+ else
184
+ raise "Unknown interpolation variable '#{ref}' referenced by value '#{value}'"
185
+ end
186
+ end
187
+ end
188
+
170
189
  def run_shell_command(command)
171
190
  ShellCommandRunner.new(console: console).run(command)
172
191
  end
@@ -9,7 +9,7 @@ module Shred
9
9
  LONGDESC
10
10
  def init
11
11
  run_shell_command(ShellCommand.new(
12
- command_lines: 'bin/rake db:create db:structure:load',
12
+ command_lines: 'bin/rake db:create:all db:structure:load',
13
13
  success_msg: 'Database initialized',
14
14
  error_msg: 'Database could not be initialized'
15
15
  ))
@@ -23,6 +23,27 @@ module Shred
23
23
  error_msg: 'Migrations could not be applied'
24
24
  ))
25
25
  end
26
+
27
+ desc 'dump', 'Dump the contents of the database to a file'
28
+ def dump
29
+ command_lines = Array(cfg('dump')).map { |v| interpolate_value(v) }
30
+ run_shell_command(ShellCommand.new(
31
+ command_lines: command_lines,
32
+ success_msg: 'Database dumped',
33
+ error_msg: 'Database could not be dumped'
34
+ ))
35
+ end
36
+
37
+ desc 'restore DUMPFILE', 'Load the contents of a dump file into the database'
38
+ def restore(dumpfile)
39
+ context = {dumpfile: dumpfile}
40
+ command_lines = Array(cfg('restore')).map { |v| interpolate_value(v, context: context) }
41
+ run_shell_command(ShellCommand.new(
42
+ command_lines: command_lines,
43
+ success_msg: 'Database restored',
44
+ error_msg: 'Database could not be restored'
45
+ ))
46
+ end
26
47
  end
27
48
  end
28
49
  end
@@ -1,6 +1,6 @@
1
- require 'shred/commands/base'
2
1
  require 'dotenv'
3
2
  require 'platform-api'
3
+ require 'shred/commands/base'
4
4
 
5
5
  module Shred
6
6
  module Commands
@@ -23,27 +23,32 @@ module Shred
23
23
 
24
24
  run_shell_command(ShellCommand.new(command_lines: 'heroku auth:whoami'))
25
25
 
26
- io = StringIO.new
26
+ heroku = StringIO.new
27
27
  run_shell_command(ShellCommand.new(
28
28
  command_lines: "heroku config --app #{app_name} --shell",
29
- output: io
29
+ output: heroku
30
30
  ))
31
31
 
32
- File.open('.env', 'w') do |output|
33
- io.string.split("\n").each do |line|
34
- if line =~ /^([^=]+)=/ && vars.include?($1)
35
- output.write("#{line}\n")
36
- end
32
+ outvars = {}
33
+
34
+ heroku.string.split("\n").each do |line|
35
+ key, value = line.split('=', 2)
36
+ outvars[key] = value if vars.include?(key)
37
+ end
38
+
39
+ if custom
40
+ custom.each do |key, value|
41
+ outvars[key] = interpolate_value(value)
37
42
  end
38
- console.say_ok("Heroku config written to .env")
43
+ end
39
44
 
40
- if custom
41
- custom.each do |key, value|
42
- output.write("#{key}=#{value}\n")
43
- end
44
- console.say_ok("Custom config written to .env")
45
+ File.open('.env', 'w') do |dotenv|
46
+ outvars.sort_by(&:first).each do |(key, value)|
47
+ dotenv.write("#{key}=#{value}\n")
45
48
  end
46
49
  end
50
+
51
+ console.say_ok("Heroku config written to .env")
47
52
  end
48
53
  end
49
54
  end
@@ -0,0 +1,67 @@
1
+ require 'dotenv'
2
+ require 'aws-sdk'
3
+ require 'shred/commands/base'
4
+
5
+ module Shred
6
+ module Commands
7
+ class DynamoDb < Base
8
+ desc 'mktable NAME REGION READ_UNITS WRITE_UNITS', 'Create a DynamoDB table'
9
+ long_desc <<-LONGDESC
10
+ Create a DynamoDB table with the given name in the given region with the given throughput capacity.
11
+
12
+ All values are used exactly as specified. They are *not* interpolated.
13
+ LONGDESC
14
+ option :pk, type: :string, default: 'id'
15
+ option :pk_type, type: :string, default: 'string'
16
+ def mktable(name, region, read_capacity_units, write_capacity_units)
17
+ ::Dotenv.load
18
+
19
+ create_table(name, region, read_capacity_units.to_i, write_capacity_units.to_i,
20
+ hash_key: {options[:pk] => options[:pk_type]})
21
+ end
22
+
23
+ desc 'mktables', 'Create all configured DynamoDB tables'
24
+ long_desc <<-LONGDESC
25
+ Create a DynamoDB table for each element of the `commands.dynamodb.tables` config var.
26
+
27
+ If the `commands.dynamodb.table_prefix` config var is set, its value is prepended to each table name.
28
+
29
+ Prefixed table names and region names are interpolated.
30
+ LONGDESC
31
+ def mktables
32
+ ::Dotenv.load
33
+
34
+ prefix = cfg('table_prefix', required: false)
35
+
36
+ cfg('tables').each do |(name, table_cfg)|
37
+ name = "#{prefix}#{name}" if prefix
38
+ name = interpolate_value(name)
39
+ region = interpolate_value(table_cfg['region'])
40
+ read_capacity_units = table_cfg['read_capacity_units'].to_i
41
+ write_capacity_units = table_cfg['write_capacity_units'].to_i
42
+ pk = table_cfg['primary_key'].fetch('name', 'id')
43
+ pk_type = table_cfg['primary_key'].fetch('type', 'string')
44
+
45
+ create_table(name, region, read_capacity_units, write_capacity_units, hash_key: {pk => pk_type})
46
+ end
47
+ end
48
+
49
+ no_commands do
50
+ def create_table(name, region, read_capacity_units, write_capacity_units, hash_key: nil)
51
+ ddb = AWS::DynamoDB.new(region: region)
52
+ if ddb.tables[name].exists?
53
+ console.say_ok("Dynamo DB table #{name} already exists in region #{region}")
54
+ else
55
+ table = ddb.tables.create(name, read_capacity_units, write_capacity_units, hash_key)
56
+ sleep 1 while table.status == :creating
57
+ if table.status == :active
58
+ console.say_ok("Created Dynamo DB table #{name} in region #{region}")
59
+ else
60
+ console.say_err("Failed to create Dynamo DB table #{name} in region #{region}: status #{table.status}")
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,119 @@
1
+ require 'dotenv'
2
+ require 'elasticsearch'
3
+ require 'shred/commands/base'
4
+
5
+ module Shred
6
+ module Commands
7
+ class Elasticsearch < Base
8
+ desc 'mkindex NAME', 'Create a search index'
9
+ long_desc <<-LONGDESC
10
+ Create the search index with the given name.
11
+
12
+ If the `commands.elasticsearch.indexes.<name>.create` config var is present, it is taken to specify a list
13
+ of shell commands to be used to create the index. This mode supports creating indices with custom mappings
14
+ or settings.
15
+
16
+ The index name is used exactly as specified; it is *not* interpolated. However, the shell commands *are*
17
+ interpolated.
18
+ LONGDESC
19
+ def mkindex(name)
20
+ ::Dotenv.load
21
+ create_index(name, cfg("indexes.#{name}", required: false))
22
+ end
23
+
24
+ desc 'mkindices', 'Create all configured search indexes'
25
+ long_desc <<-LONGDESC
26
+ Creates each search index listed for the `commands.elasticsearch.indexes` config var.
27
+
28
+ If the `commands.elasticsearch.indexes.<name>.create` config var is present, it is taken to specify a list
29
+ of shell commands to be used to create the index. This mode supports creating indices with custom mappings
30
+ or settings.
31
+
32
+ Each index name and shell command is interpolated.
33
+ LONGDESC
34
+ def mkindices
35
+ ::Dotenv.load
36
+ Array(cfg('indexes')).each do |name, index_cfg|
37
+ create_index(name, index_cfg)
38
+ end
39
+ end
40
+
41
+ desc 'rmindex NAME', 'Delete a search index'
42
+ long_desc <<-LONGDESC
43
+ Delete the search index with the given name.
44
+
45
+ The index name is used exactly as specified; it is *not* interpolated.
46
+ LONGDESC
47
+ def rmindex(name)
48
+ ::Dotenv.load
49
+ delete_index(name)
50
+ end
51
+
52
+ desc 'rmindices', 'Delete all configured search indexes'
53
+ long_desc <<-LONGDESC
54
+ Deletes each search index listed for the `commands.elasticsearch.indexes` config var.
55
+
56
+ Each index name is interpolated.
57
+ LONGDESC
58
+ def rmindices
59
+ ::Dotenv.load
60
+ Array(cfg('indexes').keys).each do |name|
61
+ delete_index(name)
62
+ end
63
+ end
64
+
65
+ desc 'import NAME', 'Import data into a search index'
66
+ long_desc <<-LONGDESC
67
+ Imports data into the search index with the given name.
68
+
69
+ Executes one or more shell commands taken from the `commands.elasticsearch.indexes.<name>.import` config var.
70
+
71
+ The index name is used exactly as specified; it is *not* interpolated. However, the shell commands *are*
72
+ interpolated.
73
+ LONGDESC
74
+ def import(name)
75
+ ::Dotenv.load
76
+ command_lines = Array(cfg("indexes.#{name}.import")).map { |l| interpolate_value(l) }
77
+ run_shell_command(ShellCommand.new(
78
+ command_lines: command_lines,
79
+ success_msg: "Data imported into index #{name}",
80
+ error_msg: "Failed to import data into index #{name}"
81
+ ))
82
+ end
83
+
84
+ no_commands do
85
+ def client
86
+ url = interpolate_value(cfg('url'))
87
+ @client ||= ::Elasticsearch::Client.new(url: url)
88
+ end
89
+
90
+ def create_index(name, index_cfg = nil)
91
+ if index_cfg && index_cfg['create']
92
+ command_lines = Array(index_cfg['create']).map { |l| interpolate_value(l) }
93
+ run_shell_command(ShellCommand.new(
94
+ command_lines: command_lines,
95
+ success_msg: "Created index #{name}",
96
+ error_msg: "Failed to create index #{name}"
97
+ ))
98
+ else
99
+ begin
100
+ client.indices.create(index: name)
101
+ console.say_ok("Created index #{name}")
102
+ rescue ::Elasticsearch::Transport::Transport::Errors::BadRequest => e
103
+ raise unless e.to_s =~ /IndexAlreadyExistsException/
104
+ console.say_err("Index #{name} already exists")
105
+ end
106
+ end
107
+ end
108
+
109
+ def delete_index(name)
110
+ client.indices.delete(index: name)
111
+ console.say_ok("Deleted index #{name}")
112
+ rescue ::Elasticsearch::Transport::Transport::Errors::NotFound => e
113
+ raise unless e.to_s =~ /IndexMissingException/
114
+ console.say_err("Index #{name} does not exist")
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,50 @@
1
+ require 'dotenv'
2
+ require 'aws-sdk'
3
+ require 'shred/commands/base'
4
+
5
+ module Shred
6
+ module Commands
7
+ class S3 < Base
8
+ desc 'mkbucket NAME REGION', 'Create an S3 bucket'
9
+ long_desc <<-LONGDESC
10
+ Create an S3 bucket with the given name in the given region.
11
+
12
+ The bucket and region names are used exactly as specified. They are *not* interpolated.
13
+ LONGDESC
14
+ def mkbucket(name, region)
15
+ ::Dotenv.load
16
+
17
+ create_bucket(name, region)
18
+ end
19
+
20
+ desc 'mkbuckets', 'Create all configured S3 buckets'
21
+ long_desc <<-LONGDESC
22
+ Create an S3 bucket for each element of the `commands.s3.buckets` config var.
23
+
24
+ Bucket and region names are interpolated.
25
+ LONGDESC
26
+ def mkbuckets
27
+ ::Dotenv.load
28
+
29
+ cfg('buckets').each do |(key, bucket_cfg)|
30
+ name = interpolate_value(bucket_cfg['name'])
31
+ region = interpolate_value(bucket_cfg['region'])
32
+
33
+ create_bucket(name, region)
34
+ end
35
+ end
36
+
37
+ no_commands do
38
+ def create_bucket(name, region)
39
+ s3 = AWS::S3.new(region: region)
40
+ if s3.buckets[name].exists?
41
+ console.say_ok("S3 bucket #{name} already exists in region #{region}")
42
+ else
43
+ s3.buckets.create(name)
44
+ console.say_ok("Created S3 bucket #{name} in region #{region}")
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/shred/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Shred
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
data/lib/shred.rb CHANGED
@@ -2,10 +2,13 @@ require 'shred/commands/app'
2
2
  require 'shred/commands/db'
3
3
  require 'shred/commands/deploy'
4
4
  require 'shred/commands/dotenv'
5
+ require 'shred/commands/dynamo_db'
6
+ require 'shred/commands/elasticsearch'
5
7
  require 'shred/commands/js_deps'
6
8
  require 'shred/commands/platform_deps'
7
9
  require 'shred/commands/ruby_deps'
8
10
  require 'shred/commands/services'
11
+ require 'shred/commands/s3'
9
12
  require 'shred/commands/test'
10
13
  require 'shred/version'
11
14
  require 'thor'
@@ -43,13 +46,25 @@ module Shred
43
46
  subcommand 'js_deps', Commands::JsDeps
44
47
  end
45
48
  if commands.key?('db')
46
- desc 'db SUBCOMMAND ...ARGS', 'Manage the database'
49
+ desc 'db SUBCOMMAND ...ARGS', 'Manage the relational database system'
47
50
  subcommand 'db', Commands::Db
48
51
  end
49
52
  if commands.key?('dotenv')
50
53
  desc 'dotenv SUBCOMMAND ...ARGS', 'Manage the environmental configuration'
51
54
  subcommand 'dotenv', Commands::Dotenv
52
55
  end
56
+ if commands.key?('s3')
57
+ desc 's3 SUBCOMMAND ...ARGS', 'Manage Amazon S3 buckets'
58
+ subcommand 's3', Commands::S3
59
+ end
60
+ if commands.key?('dynamo_db')
61
+ desc 'dynamo_db SUBCOMMAND ...ARGS', 'Manage Amazon Dynamo DB tables'
62
+ subcommand 'dynamo_db', Commands::DynamoDb
63
+ end
64
+ if commands.key?('elasticsearch')
65
+ desc 'elasticsearch subcommand ...ARGS', 'Manage Elasticsearch indexes'
66
+ subcommand 'elasticsearch', Commands::Elasticsearch
67
+ end
53
68
  if commands.key?('test')
54
69
  desc 'test SUBCOMMAND ...ARGS', 'Run tests'
55
70
  subcommand 'test', Commands::Test
@@ -68,6 +83,7 @@ module Shred
68
83
  self.class.config['commands']['setup'].each do |(cmd, subcmd)|
69
84
  invoke(cmd.to_sym, [subcmd.to_sym])
70
85
  end
86
+ console.say_ok("Setup complete!")
71
87
  end
72
88
  end
73
89
  end
data/lib/shred.yml.tt CHANGED
@@ -3,6 +3,8 @@ commands:
3
3
  start:
4
4
  - foreman start
5
5
  db:
6
+ dump: pg_dump -Fc --no-acl --no-owner -h localhost <%= app_name %>_development > <%= app_name %>_development.dump
7
+ restore: pg_restore --verbose --clean --no-acl --no-owner -h localhost -d <%= app_name %>_development {dumpfile}
6
8
  deploy:
7
9
  default_environment: staging
8
10
  staging:
@@ -21,12 +23,42 @@ commands:
21
23
  app_name: <%= app_name %>-staging
22
24
  vars:
23
25
  - AIRBRAKE_API_KEY
26
+ - ELASTICSEARCH_URL
24
27
  custom:
25
28
  vars:
26
29
  RAILS_ENV: development
30
+ AWS_S3_BUCKET: <%= app_name %>-dev-{env:USER}
31
+ AWS_S3_REGION: us-west-2
32
+ AWS_DYNAMO_DB_REGION: us-west-2
33
+ dynamo_db:
34
+ table_prefix: 'dev-{env:USER}'
35
+ tables:
36
+ clicks:
37
+ region: '{env:AWS_DYNAMO_DB_REGION}'
38
+ primary_key:
39
+ name: uuid
40
+ type: string
41
+ read_capacity_units: 10
42
+ write_capacity_units: 10
43
+ impressions:
44
+ region: '{env:AWS_DYNAMO_DB_REGION}'
45
+ primary_key:
46
+ name: uuid
47
+ type: string
48
+ read_capacity_units: 10
49
+ write_capacity_units: 10
50
+ elasticsearch:
51
+ url: '{env:ELASTICSEARCH_URL}'
52
+ indexes:
53
+ stories-development:
54
+ create:
55
+ - thor stories:create
56
+ import:
57
+ - thor stories:index
27
58
  js_deps:
28
59
  platform_deps:
29
60
  homebrew:
61
+ - node
30
62
  - postgres
31
63
  - redis
32
64
  - heroku
@@ -53,6 +85,11 @@ commands:
53
85
  mailcatcher:
54
86
  start: mailcatcher
55
87
  stop: killall mailcatcher
88
+ s3:
89
+ buckets:
90
+ default:
91
+ name: '{env:AWS_S3_BUCKET}'
92
+ region: '{env:AWS_S3_REGION}'
56
93
  setup:
57
94
  platform_deps: install
58
95
  services: start
@@ -64,4 +101,4 @@ commands:
64
101
  server:
65
102
  - bin/rake spec
66
103
  client:
67
- - bin/rake teaspoon:run
104
+ - bin/rake teaspoon
data/shred.gemspec CHANGED
@@ -21,7 +21,9 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency 'bundler', '~> 1.7'
22
22
  spec.add_development_dependency 'rake', '~> 10.0'
23
23
 
24
+ spec.add_dependency 'aws-sdk'
24
25
  spec.add_dependency 'dotenv'
26
+ spec.add_dependency 'elasticsearch'
25
27
  spec.add_dependency 'platform-api'
26
28
  spec.add_dependency 'thor'
27
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shred
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ~>
40
40
  - !ruby/object:Gem::Version
41
41
  version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: aws-sdk
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: dotenv
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -53,6 +67,20 @@ dependencies:
53
67
  - - '>='
54
68
  - !ruby/object:Gem::Version
55
69
  version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: elasticsearch
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
56
84
  - !ruby/object:Gem::Dependency
57
85
  name: platform-api
58
86
  requirement: !ruby/object:Gem::Requirement
@@ -105,9 +133,12 @@ files:
105
133
  - lib/shred/commands/db.rb
106
134
  - lib/shred/commands/deploy.rb
107
135
  - lib/shred/commands/dotenv.rb
136
+ - lib/shred/commands/dynamo_db.rb
137
+ - lib/shred/commands/elasticsearch.rb
108
138
  - lib/shred/commands/js_deps.rb
109
139
  - lib/shred/commands/platform_deps.rb
110
140
  - lib/shred/commands/ruby_deps.rb
141
+ - lib/shred/commands/s3.rb
111
142
  - lib/shred/commands/services.rb
112
143
  - lib/shred/commands/test.rb
113
144
  - lib/shred/version.rb