lambda_wrap 0.26.0 → 0.26.6

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.
@@ -1,176 +1,181 @@
1
- require 'aws-sdk'
2
-
3
- module LambdaWrap
4
- # The DynamoDBManager simplifies setting up and destroying a DynamoDB database.
5
- #
6
- # Note: In case an environment specific DynamoDB tablename such as +<baseTableName>-production+ should be used, then
7
- # it has to be injected directly to the methods since not all environments necessarily need separated databases.
8
- class DynamoDbManager
9
- ##
10
- # The constructor does some basic setup
11
- # * Validating basic AWS configuration
12
- # * Creating the underlying client to interact with the AWS SDK.
13
- def initialize
14
- # AWS dynamodb client
15
- @client = Aws::DynamoDB::Client.new
16
- end
17
-
18
- def set_table_capacity(table_name, read_capacity, write_capacity)
19
- puts "Updating new read/write capacity for table #{table_name}.
20
- Read #{table_details.provisioned_throughput.read_capacity_units} ==> #{read_capacity}.
21
- Write #{table_details.provisioned_throughput.write_capacity_units} ==> #{write_capacity}."
22
- @client.update_table(
23
- table_name: table_name,
24
- provisioned_throughput: { read_capacity_units: read_capacity, write_capacity_units: write_capacity }
25
- )
26
- end
27
-
28
- ##
29
- # Updates the provisioned throughput read and write capacity of the requested table.
30
- # If the table does not exist an error message is displayed. If current read/write capacity
31
- # is equals to requested read/write capacity or the requested read/write capacity is 0 or less than 0
32
- # no table updation is performed.
33
- #
34
- # *Arguments*
35
- # [table_name] The table name of the dynamoDB to be updated.
36
- # [read_capacity] The read capacity the table should be updated with.
37
- # [write_capacity] The write capacity the table should be updated with.
38
- def update_table_capacity(table_name, read_capacity, write_capacity)
39
- # Check if table exists.
40
- begin
41
- table_details = @client.describe_table(table_name: table_name).table
42
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
43
- raise "Update cannot be performed. Table #{table_name} does not exists."
44
- end
45
-
46
- if (read_capacity <= 0 || write_capacity <= 0)
47
- puts "Table: #{table_name} not updated. Read/Write capacity should be greater than or equal to 1."
48
- elsif (read_capacity == table_details.provisioned_throughput.read_capacity_units ||
49
- write_capacity == table_details.provisioned_throughput.write_capacity_units)
50
- puts "Table: #{table_name} not updated. Current and requested reads/writes are same.
51
- Current ReadCapacityUnits provisioned for the table: #{table_details.provisioned_throughput.read_capacity_units}.
52
- Requested ReadCapacityUnits: #{read_capacity}.
53
- Current WriteCapacityUnits provisioned for the table: #{table_details.provisioned_throughput.write_capacity_units}.
54
- Requested WriteCapacityUnits: #{write_capacity}. "
55
- else
56
- response = @client.update_table(
57
- table_name: table_name,
58
- provisioned_throughput: { read_capacity_units: read_capacity, write_capacity_units: write_capacity })
59
-
60
- raise "Read and writes capacities was not updated for table: #{table_name}." unless (response.table_description.provisioned_throughput.read_capacity_units!= read_capacity ||
61
- response.table_description.provisioned_throughput.write_capacity_units!= write_capacity)
62
-
63
- puts "Updated new read/write capacity for table #{table_name}.
64
- Read capacity updated to: #{read_capacity}.
65
- Write capacity updated to: #{write_capacity}."
66
- end
67
- end
68
-
69
- ##
70
- # Publishes the database and awaits until it is fully available. If the table already exists,
71
- # it only adjusts the read and write
72
- # capacities upwards (it doesn't downgrade them to avoid a production environment being impacted with
73
- # a default setting of an automated script).
74
- #
75
- # *Arguments*
76
- # [table_name] The table name of the dynamoDB to be created.
77
- # [attribute_definitions] The dynamoDB attribute definitions to be used when the table is created.
78
- # [key_schema] The dynamoDB key definitions to be used when the table is created.
79
- # [read_capacity] The read capacity to configure for the dynamoDB table.
80
- # [write_capacity] The write capacity to configure for the dynamoDB table.
81
- # [local_secondary_indexes] The local secondary indexes to be created.
82
- # [global_secondary_indexes] The global secondary indexes to be created.
83
- def publish_database(
84
- table_name, attribute_definitions, key_schema, read_capacity, write_capacity, local_secondary_indexes = nil,
85
- global_secondary_indexes = nil
86
- )
87
- has_updates = false
88
-
89
- # figure out whether the table exists
90
- begin
91
- table_details = @client.describe_table(table_name: table_name).table
92
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
93
- # skip this exception because we are using it for control flow.
94
- table_details = nil
95
- end
96
-
97
- if table_details
98
- wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
99
-
100
- if read_capacity > table_details.provisioned_throughput.read_capacity_units ||
101
- write_capacity > table_details.provisioned_throughput.write_capacity_units
102
-
103
- set_table_capacity read_capacity, write_capacity
104
- has_updates = true
105
- else
106
- puts "Table #{table_name} already exists and the desired read capacity of #{read_capacity} and " \
107
- "write capacity of #{write_capacity} has at least been configured. Downgrading capacity units is not " \
108
- 'supported. No changes were applied.'
109
- end
110
- else
111
- puts "Creating table #{table_name}."
112
- ad = attribute_definitions || [{ attribute_name: 'Id', attribute_type: 'S' }]
113
- ks = key_schema || [{ attribute_name: 'Id', key_type: 'HASH' }]
114
-
115
- params = {
116
- table_name: table_name, key_schema: ks, attribute_definitions: ad,
117
- provisioned_throughput: {
118
- read_capacity_units: read_capacity, write_capacity_units: write_capacity
119
- }
120
- }
121
-
122
- params[:local_secondary_indexes] = local_secondary_indexes if local_secondary_indexes != nil
123
- params[:global_secondary_indexes] = global_secondary_indexes if global_secondary_indexes != nil
124
-
125
- @client.create_table(params)
126
- has_updates = true
127
- end
128
-
129
- if has_updates
130
- wait_until_table_available(table_name)
131
- puts "DynamoDB table #{table_name} is now fully available."
132
- end
133
- end
134
-
135
- ##
136
- # Deletes a DynamoDB table. It does not wait until the table has been deleted.
137
- #
138
- # *Arguments*
139
- # [table_name] The dynamoDB table name to delete.
140
- def delete_database(table_name)
141
- table_details = @client.describe_table(table_name: table_name).table
142
- wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
143
- @client.delete_table(table_name: table_name)
144
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
145
- puts 'Table did not exist. Nothing to delete.'
146
- end
147
-
148
- ##
149
- # Awaits a given status of a table.
150
- #
151
- # *Arguments*
152
- # [table_name] The dynamoDB table name to watch until it reaches an active status.
153
- def wait_until_table_available(table_name)
154
- max_attempts = 24
155
- delay_between_attempts = 5
156
-
157
- # wait until the table has updated to being fully available
158
- # waiting for ~2min at most; an error will be thrown afterwards
159
- begin
160
- @client.wait_until(:table_exists, table_name: table_name) do |w|
161
- w.max_attempts = max_attempts
162
- w.delay = delay_between_attempts
163
- w.before_wait do |attempts, _|
164
- puts "Waiting until table becomes available. Attempt #{attempts}/#{max_attempts} " \
165
- "with polling interval #{delay_between_attempts}."
166
- end
167
- end
168
- rescue Aws::Waiters::Errors::TooManyAttemptsError => e
169
- puts "Table #{table_name} did not become available after #{e.attempts} attempts. " \
170
- 'Try again later or inspect the AWS console.'
171
- end
172
- end
173
-
174
- private :wait_until_table_available
175
- end
176
- end
1
+ require 'aws-sdk'
2
+
3
+ module LambdaWrap
4
+ # The DynamoDBManager simplifies setting up and destroying a DynamoDB database.
5
+ #
6
+ # Note: In case an environment specific DynamoDB tablename such as +<baseTableName>-production+ should be used, then
7
+ # it has to be injected directly to the methods since not all environments necessarily need separated databases.
8
+ class DynamoDbManager
9
+ ##
10
+ # The constructor does some basic setup
11
+ # * Validating basic AWS configuration
12
+ # * Creating the underlying client to interact with the AWS SDK.
13
+ def initialize
14
+ @client = Aws::DynamoDB::Client.new
15
+ end
16
+
17
+ def set_table_capacity(table_name, read_capacity, write_capacity)
18
+ puts "Updating new read/write capacity for table #{table_name}.
19
+ Read #{table_details.provisioned_throughput.read_capacity_units} ==> #{read_capacity}.
20
+ Write #{table_details.provisioned_throughput.write_capacity_units} ==> #{write_capacity}."
21
+ @client.update_table(
22
+ table_name: table_name,
23
+ provisioned_throughput: { read_capacity_units: read_capacity, write_capacity_units: write_capacity }
24
+ )
25
+ end
26
+
27
+ ##
28
+ # Updates the provisioned throughput read and write capacity of the requested table.
29
+ # If the table does not exist an error message is displayed. If current read/write capacity
30
+ # is equals to requested read/write capacity or the requested read/write capacity is 0 or less than 0
31
+ # no table updation is performed.
32
+ #
33
+ # *Arguments*
34
+ # [table_name] The table name of the dynamoDB to be updated.
35
+ # [read_capacity] The read capacity the table should be updated with.
36
+ # [write_capacity] The write capacity the table should be updated with.
37
+ def update_table_capacity(table_name, read_capacity, write_capacity)
38
+ table_details = get_table_details(table_name)
39
+ raise "Update cannot be performed. Table #{table_name} does not exists." if table_details.nil?
40
+
41
+ wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
42
+
43
+ if read_capacity <= 0 || write_capacity <= 0
44
+ puts "Table: #{table_name} not updated. Read/Write capacity should be greater than or equal to 1."
45
+ elsif read_capacity == table_details.provisioned_throughput.read_capacity_units ||
46
+ write_capacity == table_details.provisioned_throughput.write_capacity_units
47
+ puts "Table: #{table_name} not updated. Current and requested reads/writes are same."
48
+ puts 'Current ReadCapacityUnits provisioned for the table: ' \
49
+ "#{table_details.provisioned_throughput.read_capacity_units}."
50
+ puts "Requested ReadCapacityUnits: #{read_capacity}."
51
+ puts 'Current WriteCapacityUnits provisioned for the table: ' \
52
+ "#{table_details.provisioned_throughput.write_capacity_units}."
53
+ puts "Requested WriteCapacityUnits: #{write_capacity}."
54
+ else
55
+ response = @client.update_table(
56
+ table_name: table_name,
57
+ provisioned_throughput: { read_capacity_units: read_capacity, write_capacity_units: write_capacity }
58
+ )
59
+
60
+ if response.table_description.table_status == 'UPDATING'
61
+ puts "Updated new read/write capacity for table #{table_name}.
62
+ Read capacity updated to: #{read_capacity}.
63
+ Write capacity updated to: #{write_capacity}."
64
+ else
65
+ raise "Read and writes capacities was not updated for table: #{table_name}."
66
+ end
67
+ end
68
+ end
69
+
70
+ ##
71
+ # Publishes the database and awaits until it is fully available. If the table already exists, it only adjusts the
72
+ # read and write capacities upwards (it doesn't downgrade them to avoid a production environment being impacted with
73
+ # a default setting of an automated script).
74
+ #
75
+ # *Arguments*
76
+ # [table_name] The table name of the dynamoDB to be created.
77
+ # [attribute_definitions] The dynamoDB attribute definitions to be used when the table is created.
78
+ # [key_schema] The dynamoDB key definitions to be used when the table is created.
79
+ # [read_capacity] The read capacity to configure for the dynamoDB table.
80
+ # [write_capacity] The write capacity to configure for the dynamoDB table.
81
+ # [local_secondary_indexes] The local secondary indexes to be created.
82
+ # [global_secondary_indexes] The global secondary indexes to be created.
83
+ def publish_database(
84
+ table_name, attribute_definitions, key_schema, read_capacity, write_capacity, local_secondary_indexes = nil,
85
+ global_secondary_indexes = nil
86
+ )
87
+ has_updates = false
88
+
89
+ table_details = get_table_details(table_name)
90
+
91
+ if !table_details.nil?
92
+ wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
93
+
94
+ if read_capacity > table_details.provisioned_throughput.read_capacity_units ||
95
+ write_capacity > table_details.provisioned_throughput.write_capacity_units
96
+ set_table_capacity(read_capacity, write_capacity)
97
+ has_updates = true
98
+ else
99
+ puts "Table #{table_name} already exists and the desired read capacity of #{read_capacity} and " \
100
+ "write capacity of #{write_capacity} has at least been configured. Downgrading capacity units is not " \
101
+ 'supported. No changes were applied.'
102
+ end
103
+ else
104
+ puts "Creating table #{table_name}."
105
+ ad = attribute_definitions || [{ attribute_name: 'Id', attribute_type: 'S' }]
106
+ ks = key_schema || [{ attribute_name: 'Id', key_type: 'HASH' }]
107
+
108
+ params = {
109
+ table_name: table_name, key_schema: ks, attribute_definitions: ad,
110
+ provisioned_throughput: {
111
+ read_capacity_units: read_capacity, write_capacity_units: write_capacity
112
+ }
113
+ }
114
+
115
+ params[:local_secondary_indexes] = local_secondary_indexes unless local_secondary_indexes.nil?
116
+ params[:global_secondary_indexes] = global_secondary_indexes unless global_secondary_indexes.nil?
117
+
118
+ @client.create_table(params)
119
+ has_updates = true
120
+ end
121
+
122
+ if has_updates
123
+ wait_until_table_available(table_name)
124
+ puts "DynamoDB table #{table_name} is now fully available."
125
+ end
126
+ end
127
+
128
+ ##
129
+ # Deletes a DynamoDB table. It does not wait until the table has been deleted.
130
+ #
131
+ # *Arguments*
132
+ # [table_name] The dynamoDB table name to delete.
133
+ def delete_database(table_name)
134
+ table_details = get_table_details(table_name)
135
+ if table_details.nil?
136
+ puts 'Table did not exist. Nothing to delete.'
137
+ else
138
+ wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
139
+ @client.delete_table(table_name: table_name)
140
+ end
141
+ end
142
+
143
+ ##
144
+ # Awaits a given status of a table.
145
+ #
146
+ # *Arguments*
147
+ # [table_name] The dynamoDB table name to watch until it reaches an active status.
148
+ def wait_until_table_available(table_name)
149
+ max_attempts = 24
150
+ delay_between_attempts = 5
151
+
152
+ # wait until the table has updated to being fully available
153
+ # waiting for ~2min at most; an error will be thrown afterwards
154
+ begin
155
+ @client.wait_until(:table_exists, table_name: table_name) do |w|
156
+ w.max_attempts = max_attempts
157
+ w.delay = delay_between_attempts
158
+ w.before_wait do |attempts, _|
159
+ puts "Waiting until table becomes available. Attempt #{attempts}/#{max_attempts} " \
160
+ "with polling interval #{delay_between_attempts}."
161
+ end
162
+ end
163
+ rescue Aws::Waiters::Errors::TooManyAttemptsError => e
164
+ puts "Table #{table_name} did not become available after #{e.attempts} attempts. " \
165
+ 'Try again later or inspect the AWS console.'
166
+ end
167
+ end
168
+
169
+ def get_table_details(table_name)
170
+ table_details = nil
171
+ begin
172
+ table_details = @client.describe_table(table_name: table_name).table
173
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException
174
+ puts "Table #{table_name} does not exist."
175
+ end
176
+ table_details
177
+ end
178
+
179
+ private :wait_until_table_available, :get_table_details
180
+ end
181
+ end