awful 0.0.61 → 0.0.62

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: 9de77c555253db18fb3501a860fd378a2285ae7e
4
- data.tar.gz: 9874f168edca11bab394839f8a85426bc92aa9eb
3
+ metadata.gz: f95833d42a45ebbe11943600ad47c0154f6d971d
4
+ data.tar.gz: b155483d0719e88268210fbfed8d18770e3cc612
5
5
  SHA512:
6
- metadata.gz: 2d63c654d168b348bd4e90a3c54fbc8b6b9f9fc053c21260ee15dea4fa6b8766aa086f6a7477d12a432ca42dbaf374f1fcb23ab2bfdc072589ea9f9a1924a128
7
- data.tar.gz: 80d40f3d3dd3efb35d613ba326eff0fcaa4e4d19a1253e338481c5952865c1d90cfc3d54413ef89079677fe3e0d21f55b25329937e5d68d3a6afb0b7b36636f6
6
+ metadata.gz: 6f4a1db5f374f27bac8baf813c0748c4db2a913f3c6600047c943e8c20241164cbed0efdad9ba9460515a09108a49314fd6a337fdc4eb7ddefcd2d69d6bab358
7
+ data.tar.gz: a594f7e829d45a30c788d2ba7c822183a983b02fa44a85b4a7d491bd7cb662cb43aa0a96095c1aa9441fe15cacca3ea7d5c94470464f1b31801af13a680d2948
@@ -75,6 +75,21 @@ module Awful
75
75
  dynamodb.create_table(params)
76
76
  end
77
77
 
78
+ desc 'throughput NAME', 'get or update provisioned throughput for table NAME'
79
+ method_option :read_capacity_units, aliases: '-r', type: :numeric, default: nil, desc: 'Read capacity units'
80
+ method_option :write_capacity_units, aliases: '-w', type: :numeric, default: nil, desc: 'Write capacity units'
81
+ def throughput(name)
82
+ provisioned = dynamodb.describe_table(table_name: name).table.provisioned_throughput.to_h
83
+ provisioned.merge!(symbolize_keys(options))
84
+ if options.empty? # just print current throughput
85
+ provisioned.tap do |p|
86
+ puts YAML.dump(stringify_keys(p))
87
+ end
88
+ else # update from options
89
+ dynamodb.update_table(table_name: name, provisioned_throughput: only_keys_matching(provisioned, %i[read_capacity_units write_capacity_units]))
90
+ end
91
+ end
92
+
78
93
  desc 'delete NAME', 'delete table with NAME'
79
94
  def delete_table(name)
80
95
  confirmation = ask("to delete #{name} and all its data, type the name of table to delete:", :yellow)
@@ -87,6 +102,7 @@ module Awful
87
102
  end
88
103
 
89
104
  no_commands do
105
+
90
106
  ## uses simple_json to get Aws::Plugins::Protocols::JsonRpc output from scan;
91
107
  ## this also means request params need to be raw strings and not symbols, etc
92
108
  def scan_to_file(name, exclusive_start_key, fd)
@@ -100,6 +116,55 @@ module Awful
100
116
  scan_to_file(name, r['LastEvaluatedKey'], fd)
101
117
  end
102
118
  end
119
+
120
+ end
121
+
122
+ desc 'copy [region/]SRC [region/]DEST', 'copy data from table region/SRC to table region/DEST'
123
+ method_option :dots, aliases: '-d', type: :boolean, default: false, desc: 'Show dots for put_item progress'
124
+ method_option :no_clobber, aliases: '-n', type: :boolean, default: false, desc: 'Do not overwrite existing items'
125
+ def copy(src, dst)
126
+ src_table, src_region = src.split('/').reverse # parse region/table into [table, region]
127
+ dst_table, dst_region = dst.split('/').reverse
128
+
129
+ ## clients are potentially for different regions
130
+ src_client = Aws::DynamoDB::Client.new({region: src_region}.reject{|_,v| v.nil?})
131
+ dst_client = Aws::DynamoDB::Client.new({region: dst_region}.reject{|_,v| v.nil?})
132
+
133
+ ## params for put_item call
134
+ params = {table_name: dst_table}
135
+
136
+ ## add condition not to overwrite existing primary keys (hash or composite hash AND range)
137
+ if options[:no_clobber]
138
+ keys = dst_client.describe_table(table_name: dst_table).table.key_schema.map(&:attribute_name)
139
+ params.merge!(condition_expression: keys.map{|key| "attribute_not_exists(#{key})"}.join(' AND '))
140
+ end
141
+
142
+ ## lame progress indicator, pass true for put, false for skip
143
+ dots = options[:dots] ? ->(x){print x ? '.' : 'x'} : ->{}
144
+
145
+ ## recursive closure to scan some items from src and put to dest;
146
+ ## would be more studly as an anonymous y-combinator, but we should write readable code instead
147
+ scan_and_put = ->(myself, key) {
148
+ r = src_client.scan(table_name: src_table, exclusive_start_key: key, return_consumed_capacity: 'INDEXES')
149
+ print "[#{Time.now}] Scanned #{r.count} items; last evaluated key: #{r.last_evaluated_key}"
150
+ r.items.each do |item|
151
+ begin
152
+ dst_client.put_item(params.merge(item: item))
153
+ dots.call(true)
154
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException #item key exists
155
+ dots.call(false)
156
+ end
157
+ end
158
+ print "\n"
159
+
160
+ ## recurse if there are more keys to scan
161
+ if r.last_evaluated_key
162
+ myself.call(myself, r.last_evaluated_key)
163
+ end
164
+ }
165
+
166
+ ## start scanning data
167
+ scan_and_put.call(scan_and_put, nil)
103
168
  end
104
169
 
105
170
  desc 'scan NAME', 'scan table with NAME'
@@ -111,14 +176,52 @@ module Awful
111
176
  end
112
177
 
113
178
  desc 'put_items NAME', 'puts json items into the table with NAME'
179
+ method_option :no_clobber, aliases: '-n', type: :boolean, default: false, desc: 'Do not overwrite existing items'
114
180
  def put_items(name, file = nil)
181
+ params = {'TableName' => name}
182
+
183
+ ## set a condition not to overwrite items with existing primary key(s)
184
+ if options[:no_clobber]
185
+ keys = dynamodb.describe_table(table_name: name).table.key_schema.map(&:attribute_name)
186
+ params.merge!('ConditionExpression' => keys.map{|key| "attribute_not_exists(#{key})"}.join(' AND '))
187
+ end
188
+
189
+ ## input data
115
190
  io = (file and File.open(file)) || ((not $stdin.tty?) and $stdin)
116
- count = 0
191
+
192
+ put_count = 0
193
+ skip_count = 0
117
194
  io.each_line do |line|
118
- dynamodb_simple.put_item('TableName' => name, 'Item' => JSON.parse(line))
119
- count += 1
195
+ begin
196
+ dynamodb_simple.put_item(params.merge('Item' => JSON.parse(line)))
197
+ put_count += 1
198
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException #item key exists
199
+ skip_count += 1
200
+ end
201
+ end
202
+
203
+ ## return counts
204
+ [put_count, skip_count].tap do |put, skip|
205
+ puts "put #{put} items, skipped #{skip} items"
206
+ end
207
+ end
208
+
209
+ desc 'batch_write NAME', 'batch write items to table NAME'
210
+ def batch_write(name)
211
+ items = (1..25).map do |n|
212
+ {
213
+ put_request: {
214
+ item: {
215
+ "store_id" => "store#{n}",
216
+ "object_id" => "object#{n}",
217
+ "object_value" => "value#{n}"
218
+ }
219
+ }
220
+ }
120
221
  end
121
- count.tap { |c| puts "put #{c} items" }
222
+ p items
223
+ r = dynamodb.batch_write_item(request_items: {name => items})
224
+ p r
122
225
  end
123
226
 
124
227
  end
@@ -1,3 +1,3 @@
1
1
  module Awful
2
- VERSION = "0.0.61"
2
+ VERSION = "0.0.62"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.61
4
+ version: 0.0.62
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ric Lister
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-10 00:00:00.000000000 Z
11
+ date: 2015-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler