dyna 0.1.1
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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/dyna +191 -0
- data/dyna.gemspec +32 -0
- data/lib/dyna/client.rb +89 -0
- data/lib/dyna/dsl/converter.rb +87 -0
- data/lib/dyna/dsl/dynamo_db.rb +31 -0
- data/lib/dyna/dsl/table.rb +112 -0
- data/lib/dyna/dsl.rb +54 -0
- data/lib/dyna/exporter.rb +105 -0
- data/lib/dyna/ext/hash-ext.rb +12 -0
- data/lib/dyna/ext/string-ext.rb +25 -0
- data/lib/dyna/filterable.rb +21 -0
- data/lib/dyna/logger.rb +30 -0
- data/lib/dyna/template_helper.rb +20 -0
- data/lib/dyna/utils.rb +17 -0
- data/lib/dyna/version.rb +3 -0
- data/lib/dyna/wrapper/dynamo_db_wrapper.rb +31 -0
- data/lib/dyna/wrapper/table.rb +205 -0
- data/lib/dyna.rb +27 -0
- metadata +181 -0
data/lib/dyna/dsl.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Dyna
|
2
|
+
class DSL
|
3
|
+
include Dyna::TemplateHelper
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def define(source, path)
|
7
|
+
self.new(path) do
|
8
|
+
eval(source, binding, path)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def convert(region, exported)
|
13
|
+
Converter.convert(region, exported)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :result
|
18
|
+
|
19
|
+
def initialize(path, &block)
|
20
|
+
@path = path
|
21
|
+
@result = OpenStruct.new(:ddbs => {})
|
22
|
+
|
23
|
+
@context = Hashie::Mash.new(
|
24
|
+
:path => path,
|
25
|
+
:templates => {},
|
26
|
+
)
|
27
|
+
|
28
|
+
instance_eval(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def template(name, &block)
|
33
|
+
@context.templates[name.to_s] = block
|
34
|
+
end
|
35
|
+
|
36
|
+
def require(file)
|
37
|
+
tablefile = (file =~ %r|\A/|) ? file : File.expand_path(File.join(File.dirname(@path), file))
|
38
|
+
|
39
|
+
if File.exist?(tablefile)
|
40
|
+
instance_eval(File.read(tablefile), tablefile)
|
41
|
+
elsif File.exist?(tablefile + '.rb')
|
42
|
+
instance_eval(File.read(tablefile + '.rb'), tablefile + '.rb')
|
43
|
+
else
|
44
|
+
Kernel.require(file)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def dynamo_db(region, &block)
|
49
|
+
ddb = @result.ddbs[region]
|
50
|
+
tables = ddb ? ddb.tables : []
|
51
|
+
@result.ddbs[region] = DynamoDB.new(@context, tables, &block).result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Dyna
|
2
|
+
class Exporter
|
3
|
+
include Filterable
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def export(ddb, options = {})
|
7
|
+
self.new(ddb, options).export
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(ddb, options = {})
|
12
|
+
@ddb = ddb
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def export
|
17
|
+
@ddb.list_tables.table_names
|
18
|
+
.reject { |name| should_skip(name) }
|
19
|
+
.sort
|
20
|
+
.each_with_object({}) do |table_name, result|
|
21
|
+
result[table_name] = self.class.export_table(@ddb, table_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.table_definition(describe_table)
|
26
|
+
{
|
27
|
+
table_name: describe_table.table_name,
|
28
|
+
key_schema: key_schema(describe_table),
|
29
|
+
attribute_definitions: attribute_definitions(describe_table),
|
30
|
+
provisioned_throughput: {
|
31
|
+
read_capacity_units: describe_table.provisioned_throughput.read_capacity_units,
|
32
|
+
write_capacity_units: describe_table.provisioned_throughput.write_capacity_units,
|
33
|
+
},
|
34
|
+
local_secondary_indexes: local_secondary_indexes(describe_table),
|
35
|
+
global_secondary_indexes: global_secondary_indexes(describe_table),
|
36
|
+
stream_specification: stream_specification(describe_table),
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def self.export_table(ddb, table_name)
|
42
|
+
describe_table = ddb.describe_table(table_name: table_name).table
|
43
|
+
table_definition(describe_table)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.key_schema(table)
|
47
|
+
table.key_schema.map do |schema|
|
48
|
+
{
|
49
|
+
attribute_name: schema.attribute_name,
|
50
|
+
key_type: schema.key_type,
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.attribute_definitions(table)
|
56
|
+
table.attribute_definitions.map do |definition|
|
57
|
+
{
|
58
|
+
attribute_name: definition.attribute_name,
|
59
|
+
attribute_type: definition.attribute_type,
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.global_secondary_indexes(table)
|
65
|
+
return nil unless table.global_secondary_indexes
|
66
|
+
table.global_secondary_indexes.map do |index|
|
67
|
+
{
|
68
|
+
index_name: index.index_name,
|
69
|
+
key_schema: key_schema(index),
|
70
|
+
projection: {
|
71
|
+
projection_type: index.projection.projection_type,
|
72
|
+
non_key_attributes: index.projection.non_key_attributes,
|
73
|
+
},
|
74
|
+
provisioned_throughput: {
|
75
|
+
read_capacity_units: index.provisioned_throughput.read_capacity_units,
|
76
|
+
write_capacity_units: index.provisioned_throughput.write_capacity_units,
|
77
|
+
},
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.local_secondary_indexes(table)
|
83
|
+
return nil unless table.local_secondary_indexes
|
84
|
+
table.local_secondary_indexes.map do |index|
|
85
|
+
{
|
86
|
+
index_name: index.index_name,
|
87
|
+
key_schema: key_schema(index),
|
88
|
+
projection: {
|
89
|
+
projection_type: index.projection.projection_type,
|
90
|
+
non_key_attributes: index.projection.non_key_attributes,
|
91
|
+
},
|
92
|
+
}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.stream_specification(table)
|
97
|
+
stream_spec = table.stream_specification
|
98
|
+
return nil unless stream_spec
|
99
|
+
{
|
100
|
+
stream_enabled: stream_spec.stream_enabled,
|
101
|
+
stream_view_type: stream_spec.stream_view_type,
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Hash
|
2
|
+
def symbolize_keys
|
3
|
+
self.each_with_object({}) do |(k, v), h|
|
4
|
+
h[k.to_s.to_sym] = (v.is_a?(Hash) ? v.symbolize_keys : v)
|
5
|
+
if v.is_a?(Array)
|
6
|
+
h[k.to_s.to_sym] = v.each_with_object([]) do |h2, a|
|
7
|
+
a << (h2.is_a?(Hash) ? h2.symbolize_keys : h2)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class String
|
2
|
+
@@colorize = false
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def colorize=(value)
|
6
|
+
@@colorize = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def colorize
|
10
|
+
@@colorize
|
11
|
+
end
|
12
|
+
end # of class methods
|
13
|
+
|
14
|
+
Term::ANSIColor::Attribute.named_attributes.map do |attribute|
|
15
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
16
|
+
def #{attribute.name}
|
17
|
+
if @@colorize
|
18
|
+
Term::ANSIColor.send(#{attribute.name.inspect}, self)
|
19
|
+
else
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
EOS
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Dyna
|
2
|
+
module Filterable
|
3
|
+
def should_skip(table_name)
|
4
|
+
if @options.table_names
|
5
|
+
unless @options.table_names.include?(table_name)
|
6
|
+
log(:debug, "skip table(with tables_names option) #{table_name}")
|
7
|
+
return true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
if @options.exclude_table_names
|
12
|
+
if @options.exclude_table_names.any? {|regex| table_name =~ regex}
|
13
|
+
log(:debug, "skip table(with exclude_tables_names option) #{table_name}")
|
14
|
+
return true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/dyna/logger.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Dyna
|
2
|
+
class Logger < ::Logger
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
super($stdout)
|
7
|
+
|
8
|
+
self.formatter = proc do |severity, datetime, progname, msg|
|
9
|
+
"#{msg}\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
self.level = Logger::INFO
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_debug(value)
|
16
|
+
self.level = value ? Logger::DEBUG : Logger::INFO
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClientHelper
|
20
|
+
def log(level, message, color, log_id = nil)
|
21
|
+
message = "[#{level.to_s.upcase}] #{message}" unless level == :info
|
22
|
+
message << ": #{log_id}" if log_id
|
23
|
+
message << ' (dry-run)' if @options && @options.dry_run
|
24
|
+
logger = (@options && @options.logger) || Dyna::Logger.instance
|
25
|
+
message = message.send(color) if color
|
26
|
+
logger.send(level, message)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dyna
|
2
|
+
module TemplateHelper
|
3
|
+
def include_template(template_name, context = {})
|
4
|
+
tmplt = @context.templates[template_name.to_s]
|
5
|
+
|
6
|
+
unless tmplt
|
7
|
+
raise "Template `#{template_name}` is not defined"
|
8
|
+
end
|
9
|
+
|
10
|
+
context_orig = @context
|
11
|
+
@context = @context.merge(context)
|
12
|
+
instance_eval(&tmplt)
|
13
|
+
@context = context_orig
|
14
|
+
end
|
15
|
+
|
16
|
+
def context
|
17
|
+
@context
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/dyna/utils.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dyna
|
2
|
+
class Utils
|
3
|
+
class << self
|
4
|
+
def diff(obj1, obj2, options = {})
|
5
|
+
diffy = Diffy::Diff.new(
|
6
|
+
obj1.pretty_inspect,
|
7
|
+
obj2.pretty_inspect,
|
8
|
+
:diff => '-u'
|
9
|
+
)
|
10
|
+
|
11
|
+
out = diffy.to_s(options[:color] ? :color : :text).gsub(/\s+\z/m, '')
|
12
|
+
out.gsub!(/^/, options[:indent]) if options[:indent]
|
13
|
+
out
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/dyna/version.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dyna
|
2
|
+
class DynamoDBWrapper
|
3
|
+
include Logger::ClientHelper
|
4
|
+
|
5
|
+
def initialize(ddb, options)
|
6
|
+
@ddb = ddb
|
7
|
+
@options = options.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
def tables
|
11
|
+
@ddb.list_tables.table_names.map do |table_name|
|
12
|
+
describe_table = @ddb.describe_table(table_name: table_name).table
|
13
|
+
Table.new(@ddb, describe_table, @options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(dsl)
|
18
|
+
log(:info, 'Create Table', :cyan, "#{dsl.table_name}")
|
19
|
+
|
20
|
+
unless @options.dry_run
|
21
|
+
result = @ddb.create_table(dsl.symbolize_keys)
|
22
|
+
@options.updated = true
|
23
|
+
result
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def updated?
|
28
|
+
!!@options.updated
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module Dyna
|
2
|
+
class DynamoDBWrapper
|
3
|
+
class Table
|
4
|
+
extend Forwardable
|
5
|
+
include Logger::ClientHelper
|
6
|
+
|
7
|
+
def_delegators(
|
8
|
+
:@table,
|
9
|
+
:table_name
|
10
|
+
)
|
11
|
+
|
12
|
+
def initialize(ddb, table, options)
|
13
|
+
@ddb = ddb
|
14
|
+
@table = table
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def eql?(dsl)
|
19
|
+
definition_eql?(dsl)
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(dsl)
|
23
|
+
unless provisioned_throughput_eql?(dsl)
|
24
|
+
wait_until_table_is_active
|
25
|
+
update_table(dsl_provisioned_throughput(dsl))
|
26
|
+
end
|
27
|
+
unless global_secondary_indexes_eql?(dsl)
|
28
|
+
wait_until_table_is_active
|
29
|
+
update_table_index(dsl, dsl_global_secondary_index_updates(dsl))
|
30
|
+
end
|
31
|
+
unless stream_specification_eql?(dsl)
|
32
|
+
wait_until_table_is_active
|
33
|
+
update_stream_specification(dsl_stream_specification(dsl))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete
|
38
|
+
log(:info, 'Delete Table', :red, "#{table_name}")
|
39
|
+
|
40
|
+
unless @options.dry_run
|
41
|
+
@ddb.delete_table(table_name: @table.table_name)
|
42
|
+
@options.updated = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def definition
|
47
|
+
Exporter.table_definition(@table).symbolize_keys
|
48
|
+
end
|
49
|
+
|
50
|
+
def wait_until_table_is_active
|
51
|
+
log(:info, "waiting table #{@table.table_name} to be ACTIVE or deleted..", false)
|
52
|
+
loop do
|
53
|
+
begin
|
54
|
+
desc = @ddb.describe_table(table_name: table_name).table
|
55
|
+
rescue => e
|
56
|
+
break
|
57
|
+
end
|
58
|
+
status = desc.table_status
|
59
|
+
log(:info, "status... #{status}", false)
|
60
|
+
break if desc.table_status == 'ACTIVE'
|
61
|
+
sleep 3
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def definition_eql?(dsl)
|
67
|
+
definition == dsl.definition
|
68
|
+
end
|
69
|
+
|
70
|
+
def provisioned_throughput_eql?(dsl)
|
71
|
+
self_provisioned_throughput == dsl_provisioned_throughput(dsl)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self_provisioned_throughput
|
75
|
+
definition.select {|k,v| k == :provisioned_throughput}
|
76
|
+
end
|
77
|
+
|
78
|
+
def dsl_provisioned_throughput(dsl)
|
79
|
+
dsl.symbolize_keys.select {|k,v| k == :provisioned_throughput}
|
80
|
+
end
|
81
|
+
|
82
|
+
def global_secondary_indexes_eql?(dsl)
|
83
|
+
self_global_secondary_indexes == dsl_global_secondary_indexes(dsl)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self_global_secondary_indexes
|
87
|
+
definition[:global_secondary_indexes]
|
88
|
+
end
|
89
|
+
|
90
|
+
def dsl_global_secondary_indexes(dsl)
|
91
|
+
dsl.symbolize_keys[:global_secondary_indexes]
|
92
|
+
end
|
93
|
+
|
94
|
+
def dsl_global_secondary_index_updates(dsl)
|
95
|
+
actual_by_name = (self_global_secondary_indexes || {}).group_by { |index| index[:index_name] }.each_with_object({}) do |(k, v), h|
|
96
|
+
h[k] = v.first
|
97
|
+
end
|
98
|
+
expect_by_name = (dsl_global_secondary_indexes(dsl) || {}).group_by { |index| index[:index_name] }.each_with_object({}) do |(k, v), h|
|
99
|
+
h[k] = v.first
|
100
|
+
end
|
101
|
+
params = []
|
102
|
+
expect_by_name.each do |index_name, expect_index|
|
103
|
+
actual_index = actual_by_name[index_name]
|
104
|
+
unless actual_index
|
105
|
+
unless params.empty?
|
106
|
+
log(:warn, 'Can not add multiple GSI at once', :yellow, index_name)
|
107
|
+
next
|
108
|
+
end
|
109
|
+
params << {create: expect_index}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
expect_by_name.each do |index_name, expect_index|
|
114
|
+
actual_index = actual_by_name.delete(index_name)
|
115
|
+
if actual_index != nil &&
|
116
|
+
actual_index[:provisioned_throughput] != expect_index[:provisioned_throughput]
|
117
|
+
if params.any? { |param| param[:update] }
|
118
|
+
log(:warn, 'Can not update multiple GSI at once', :yellow, index_name)
|
119
|
+
next
|
120
|
+
end
|
121
|
+
params << {update: {
|
122
|
+
index_name: index_name,
|
123
|
+
provisioned_throughput: expect_index[:provisioned_throughput]
|
124
|
+
}}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
actual_by_name.each do |index_name, actual_index|
|
129
|
+
if params.any? { |param| param[:delete] }
|
130
|
+
log(:warn, 'Can not delete multiple GSI at once', :yellow, index_name)
|
131
|
+
next
|
132
|
+
end
|
133
|
+
params << {delete: { index_name: index_name }}
|
134
|
+
end
|
135
|
+
|
136
|
+
params
|
137
|
+
end
|
138
|
+
|
139
|
+
def stream_specification_eql?(dsl)
|
140
|
+
actual = self_stream_specification
|
141
|
+
expect = dsl_stream_specification(dsl)
|
142
|
+
if (actual == nil || actual[:stream_specification] == nil) &&
|
143
|
+
(expect == nil || expect[:stream_specification] == nil || expect[:stream_specification][:stream_enabled] == false)
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
actual == expect
|
147
|
+
end
|
148
|
+
|
149
|
+
def self_stream_specification
|
150
|
+
definition.select {|k,v| k == :stream_specification}
|
151
|
+
end
|
152
|
+
|
153
|
+
def dsl_stream_specification(dsl)
|
154
|
+
dsl.symbolize_keys.select {|k,v| k == :stream_specification}
|
155
|
+
end
|
156
|
+
|
157
|
+
def update_stream_specification(dsl)
|
158
|
+
log(:info, " table: #{@table.table_name}(update stream spec)\n".green + Dyna::Utils.diff(self_stream_specification, dsl, :color => @options.color, :indent => ' '), false)
|
159
|
+
unless @options.dry_run
|
160
|
+
params = { table_name: @table.table_name }.merge(dsl)
|
161
|
+
@ddb.update_table(params)
|
162
|
+
@options.updated = true
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def update_table(dsl)
|
167
|
+
log(:info, " table: #{@table.table_name}\n".green + Dyna::Utils.diff(self_provisioned_throughput, dsl, :color => @options.color, :indent => ' '), false)
|
168
|
+
unless @options.dry_run
|
169
|
+
params = dsl.dup
|
170
|
+
params[:table_name] = @table.table_name
|
171
|
+
@ddb.update_table(params)
|
172
|
+
@options.updated = true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def update_table_index(dsl, index_params)
|
177
|
+
log(:info, " table: #{@table.table_name}(update GSI)".green, false)
|
178
|
+
index_params.each do |index_param|
|
179
|
+
if index_param[:create]
|
180
|
+
log(:info, " index: #{index_param[:create][:index_name]}(create GSI)".cyan, false)
|
181
|
+
log(:info, " => #{index_param[:create]}".cyan, false)
|
182
|
+
end
|
183
|
+
if index_param[:update]
|
184
|
+
log(:info, " index: #{index_param[:update][:index_name]}(update GSI)".green, false)
|
185
|
+
log(:info, " => #{index_param[:update]}".green, false)
|
186
|
+
end
|
187
|
+
if index_param[:delete]
|
188
|
+
log(:info, " index: #{index_param[:delete][:index_name]}(delete GSI)".red, false)
|
189
|
+
log(:info, " => #{index_param[:delete]}".red, false)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
unless @options.dry_run
|
194
|
+
params = {
|
195
|
+
table_name: @table.table_name,
|
196
|
+
attribute_definitions: dsl.symbolize_keys[:attribute_definitions],
|
197
|
+
global_secondary_index_updates: index_params,
|
198
|
+
}
|
199
|
+
@ddb.update_table(params)
|
200
|
+
@options.updated = true
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
data/lib/dyna.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'logger'
|
3
|
+
require 'term/ansicolor'
|
4
|
+
require 'diffy'
|
5
|
+
require 'hashie'
|
6
|
+
require 'singleton'
|
7
|
+
|
8
|
+
require 'aws-sdk'
|
9
|
+
|
10
|
+
require 'dyna/version'
|
11
|
+
require 'dyna/logger'
|
12
|
+
require 'dyna/filterable'
|
13
|
+
require 'dyna/client'
|
14
|
+
require 'dyna/exporter'
|
15
|
+
require 'dyna/template_helper'
|
16
|
+
require 'dyna/dsl'
|
17
|
+
require 'dyna/utils'
|
18
|
+
require 'dyna/dsl/converter'
|
19
|
+
require 'dyna/dsl/dynamo_db'
|
20
|
+
require 'dyna/dsl/table'
|
21
|
+
require 'dyna/ext/string-ext'
|
22
|
+
require 'dyna/ext/hash-ext'
|
23
|
+
require 'dyna/wrapper/table'
|
24
|
+
require 'dyna/wrapper/dynamo_db_wrapper'
|
25
|
+
|
26
|
+
module Dyna
|
27
|
+
end
|