awful 0.0.61 → 0.0.62

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.
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