sessel 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1310706b7c390a978b139bd724238ab1a5d1a467
4
+ data.tar.gz: 7f543438b2ef606892240352007b57aefab6f826
5
+ SHA512:
6
+ metadata.gz: b0996edb14235359fb5e33af12e94ef1cf7e128865bd1421a13ef58d7ce6c0aff6e39c12887e6dc5f291158ee075e68721c6966f1efa92ebd31c8f866584afa9
7
+ data.tar.gz: bdccf81a1e11afe1de0050a7283cb5a0819732c559c69dd0589956d910adbc2522c026e116fe114811fbb0256ba9126d16e034e757dd81b3dac33e3e05752b8c
data/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Rafal Nowosielski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # sessel
2
+
3
+ ![Image of Yaktocat](sessel.png)
4
+
5
+ Sessel - an AWS SES configuration tool
6
+
7
+ The idea behind this gem is to privide a way to automate configuration of Simple Email Service in AWS, so that the complete solution that one builds in AWS could be stored in the repository and deployed automatically.
8
+
9
+ ## Installation
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.warning = false
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
data/bin/sessel ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sessel'
4
+
5
+ Sessel::Main.start(ARGV)
data/lib/sessel.rb ADDED
@@ -0,0 +1,4 @@
1
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/**/*.rb"].each { |f| require f }
2
+
3
+ STDOUT.sync = true
4
+ STDERR.sync = true
data/lib/sessel/ask.rb ADDED
@@ -0,0 +1,73 @@
1
+ require 'highline'
2
+ require 'uri'
3
+
4
+ module Sessel
5
+
6
+ class Ask
7
+
8
+ @@cli = HighLine.new
9
+ @@ses = nil
10
+ @@s3 = nil
11
+
12
+ def self.for_region()
13
+ region = nil
14
+ @@cli.choose do |region_menu|
15
+ region_menu.prompt = "Choose AWS region you want to setup SES in?"
16
+ region_menu.choices("us-east-1", "us-west-2", "eu-west-1") { |r| region = r }
17
+ end
18
+ @@ses = Aws::SES::Client.new(region: region)
19
+ @@s3 = Aws::S3::Client.new(region: region)
20
+ return region
21
+ end
22
+
23
+ def self.for_rule_set_name(solution_name)
24
+ chosen_rule_set_name = nil
25
+ @@cli.choose do |rule_set_menu|
26
+ solution_rule_set_name = "#{solution_name}RuleSet"
27
+ rule_set_menu.prompt = 'Choose receipt rule-set?'
28
+ resp = @@ses.list_receipt_rule_sets
29
+ add_new_rule_set = true
30
+ resp.to_h[:rule_sets].each { |rule_set|
31
+ rule_set_menu.choice(rule_set[:name]) { chosen_rule_set_name = rule_set[:name] }
32
+ add_new_rule_set = false if (rule_set[:name] =~ /^#{Regexp.escape(solution_rule_set_name)}$/)
33
+ }
34
+ rule_set_menu.choice("Create new: #{solution_rule_set_name}") {
35
+ chosen_rule_set_name = solution_rule_set_name
36
+ } if add_new_rule_set
37
+ end
38
+ return chosen_rule_set_name
39
+ end
40
+
41
+ def self.for_email_address()
42
+ return @@cli.ask('What is the email address you would like to receive emails at?') {
43
+ |q| q.validate = /\w@[a-z0-9_-].[a-z]/ }
44
+ end
45
+
46
+ def self.for_s3_bucket(solution_name, region)
47
+ chosen_bucket = nil
48
+ @@cli.choose do |s3_bucket_menu|
49
+ solution_bucket_name = solution_name.downcase
50
+ s3_bucket_menu.prompt = "Choose S3 bucket to put the emails in"
51
+ resp = @@s3.list_buckets()
52
+ add_new_bucket = true
53
+ resp.to_h[:buckets].each { |bucket|
54
+ s3_bucket_menu.choice(bucket[:name]) { chosen_bucket = bucket[:name] }
55
+ add_new_bucket = false if (bucket[:name] =~ /^#{Regexp.escape(solution_bucket_name)}$/)
56
+ }
57
+ s3_bucket_menu.choice("Create new: #{solution_bucket_name}") {
58
+ @@s3.create_bucket({
59
+ acl: "private",
60
+ bucket: solution_bucket_name,
61
+ create_bucket_configuration: {
62
+ location_constraint: region
63
+ }
64
+ })
65
+ chosen_bucket = solution_name
66
+ } if add_new_bucket
67
+ end
68
+ return chosen_bucket
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,20 @@
1
+ module Sessel
2
+
3
+ class ConfigurationSet
4
+
5
+ def initialize(region, configuration_set_name)
6
+ @configuration_set_name = configuration_set_name
7
+ @region = region
8
+ end
9
+
10
+ def configuration_set_name
11
+ return @configuration_set_name
12
+ end
13
+
14
+ def region
15
+ return @region
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,58 @@
1
+ require 'uri'
2
+
3
+ module Sessel
4
+
5
+ # Takes care of creating the configuration set and making sure all the prerequisites are in place
6
+ class ConfigurationSetCreator
7
+
8
+ def initialize(configuration_set)
9
+ @configuration_set = configuration_set
10
+ @ses = Aws::SES::Client.new(region: configuration_set.region)
11
+ end
12
+
13
+ def configuration_set
14
+ return @configuration_set
15
+ end
16
+
17
+ # Creates the configuration set in SES accoring to the paramteres passed when the object was initialised
18
+ def create()
19
+
20
+ rule = {
21
+ configuration_set: {
22
+ name: @configuration_set.configuration_set_name,
23
+ }
24
+ }
25
+ begin
26
+ @ses.create_configuration_set(rule)
27
+ rescue Aws::SES::Errors::ConfigurationSetAlreadyExists
28
+ puts "#{@configuration_set.configuration_set_name} already exists. Skipping."
29
+ end
30
+
31
+ event_destinaton = {
32
+ configuration_set_name: @configuration_set.configuration_set_name,
33
+ event_destination: {
34
+ name: "#{@configuration_set.configuration_set_name}EventName",
35
+ enabled: true,
36
+ matching_event_types: ['send', 'reject', 'bounce', 'complaint', 'delivery'],
37
+ cloud_watch_destination: {
38
+ dimension_configurations: [
39
+ {
40
+ dimension_name: 'To',
41
+ dimension_value_source: 'emailHeader',
42
+ default_dimension_value: 'DestinationUnknown'
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ }
48
+ begin
49
+ @ses.create_configuration_set_event_destination(event_destinaton)
50
+ rescue Aws::SES::Errors::EventDestinationAlreadyExists
51
+ @ses.update_configuration_set_event_destination(event_destinaton)
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
data/lib/sessel/io.rb ADDED
@@ -0,0 +1,39 @@
1
+ module Sessel
2
+
3
+ class IO
4
+
5
+ def self.announce()
6
+ puts 'Question:'
7
+ ret = yield
8
+ puts "Answer: #{ret}\n\n"
9
+ return ret
10
+ end
11
+
12
+ def self.read_config_from_file()
13
+ config = {}
14
+ if File.file?(SESSEL_YAML) then
15
+ config = YAML.load File.read(SESSEL_YAML);
16
+ end
17
+ unless config[:receipt_rules] then
18
+ config[:receipt_rules] = []
19
+ end
20
+ unless config[:configuration_sets] then
21
+ config[:configuration_sets] = []
22
+ end
23
+ return config
24
+ end
25
+
26
+ def self.append_receipt_rule_to_file(receipt_rule)
27
+ config = read_config_from_file
28
+ config[:receipt_rules].push(receipt_rule)
29
+ File.open(SESSEL_YAML, 'w') { |file| file.write(config.to_yaml) }
30
+ end
31
+
32
+ def self.append_configuration_set_to_file(configuration_set)
33
+ config = read_config_from_file
34
+ config[:configuration_sets].push(configuration_set)
35
+ File.open(SESSEL_YAML, 'w') { |file| file.write(config.to_yaml) }
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,70 @@
1
+ require 'thor'
2
+ require 'aws-sdk'
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ module Sessel
7
+
8
+ SESSEL_YAML = 'sessel.yaml'
9
+
10
+ class Add < Thor
11
+
12
+ desc "receipt_rule SOLUTION_NAME", "Start setup of SES receipt rule for your particular SOLUTION_NAME"
13
+ long_desc <<-LONGDESC
14
+ Adds a new receipt rule to the configuration.
15
+ LONGDESC
16
+ def receipt_rule(solution_name)
17
+ region = IO.announce { Ask.for_region }
18
+ chosen_rule_set_name = IO.announce { Ask.for_rule_set_name(solution_name) }
19
+ email_address = IO.announce { Ask.for_email_address }
20
+ s3_bucket = IO.announce { Ask.for_s3_bucket(solution_name, region) }
21
+ rule_creator = Sessel::ReceiptRuleCreator.new(
22
+ ReceiptRule.new(region, [email_address], s3_bucket, solution_name, chosen_rule_set_name)
23
+ )
24
+ rule_creator.create
25
+ IO.append_receipt_rule_to_file(rule_creator.receipt_rule)
26
+ puts "That's it!"
27
+ end
28
+
29
+ desc "configuration_set SOLUTION_NAME", "Start setup of SES configuration set for your particular SOLUTION_NAME"
30
+ long_desc <<-LONGDESC
31
+ Adds a new configuration set into the configuration.
32
+ LONGDESC
33
+ def configuration_set(solution_name)
34
+ region = IO.announce { Ask.for_region }
35
+ configuration_set_creator = Sessel::ConfigurationSetCreator.new(
36
+ ConfigurationSet.new(region, "#{solution_name}ConfigurationSet")
37
+ )
38
+ configuration_set_creator.create
39
+ IO.append_configuration_set_to_file(configuration_set_creator.configuration_set)
40
+ puts "That's it!"
41
+ end
42
+ end
43
+
44
+ class Main < Thor
45
+
46
+ option :interactive, :type => :boolean
47
+ desc 'apply', 'Uses the sessle.yaml to providsion resources in the AWS account'
48
+ long_desc <<-LONGDESC
49
+ Uses the configuration stored in sessle.yaml to provision or uptate the recourses in the AWS account
50
+ LONGDESC
51
+ def apply
52
+ config = IO.read_config_from_file
53
+ config[:receipt_rules].each do |receipt_rule|
54
+ puts "Applying receipt rule: #{receipt_rule.rule_set_name} / #{receipt_rule.rule_name}"
55
+ rule_creator = Sessel::ReceiptRuleCreator.new(receipt_rule)
56
+ rule_creator.create
57
+ end
58
+ config[:configuration_sets].each do |configuration_set|
59
+ puts "Applying configuration set: #{configuration_set.configuration_set_name}"
60
+ configuration_set_creator = Sessel::ConfigurationSetCreator.new(configuration_set)
61
+ configuration_set_creator.create
62
+ end
63
+ puts 'Done'
64
+ end
65
+
66
+ desc 'add SUBCOMMAND ...ARGS', 'Add configuration items to the sessle.yaml.'
67
+ subcommand 'add', Add
68
+
69
+ end
70
+ end
@@ -0,0 +1,35 @@
1
+ module Sessel
2
+
3
+ class ReceiptRule
4
+
5
+ def initialize(region, email_addresses, s3_bucket, rule_name, rule_set_name)
6
+ @email_addresses = email_addresses
7
+ @region = region
8
+ @s3_bucket = s3_bucket
9
+ @rule_name = rule_name
10
+ @rule_set_name = rule_set_name
11
+ end
12
+
13
+ def email_addresses
14
+ return @email_addresses
15
+ end
16
+
17
+ def region
18
+ return @region
19
+ end
20
+
21
+ def s3_bucket
22
+ return @s3_bucket
23
+ end
24
+
25
+ def rule_name
26
+ return @rule_name
27
+ end
28
+
29
+ def rule_set_name
30
+ return @rule_set_name
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,204 @@
1
+ require 'uri'
2
+
3
+ module Sessel
4
+
5
+ # Takes care of creating the receipt rule and making sure all the prerequisites are in place
6
+ class ReceiptRuleCreator
7
+
8
+ def initialize(receipt_rule)
9
+ @receipt_rule = receipt_rule
10
+ @s3 = Aws::S3::Client.new(region: receipt_rule.region)
11
+ @sts = Aws::STS::Client.new(region: receipt_rule.region)
12
+ @ses = Aws::SES::Client.new(region: receipt_rule.region)
13
+ @route53 = Aws::Route53::Client.new(region: receipt_rule.region)
14
+ end
15
+
16
+ def receipt_rule
17
+ return @receipt_rule
18
+ end
19
+
20
+ # Creates the receipt rule in SES accorind to the paramteres passed when the object was initialised
21
+ def create()
22
+
23
+ ensure_prerequsites
24
+
25
+ rule = {
26
+ rule: {
27
+ recipients: @receipt_rule.email_addresses,
28
+ actions: [
29
+ {
30
+ s3_action: {
31
+ bucket_name: @receipt_rule.s3_bucket,
32
+ object_key_prefix: 'email',
33
+ },
34
+ },
35
+ ],
36
+ enabled: true,
37
+ name: @receipt_rule.rule_name,
38
+ scan_enabled: false,
39
+ tls_policy: 'Optional',
40
+ },
41
+ rule_set_name: @receipt_rule.rule_set_name,
42
+ }
43
+ begin
44
+ @ses.create_receipt_rule(rule)
45
+ rescue Aws::SES::Errors::AlreadyExists
46
+ @ses.update_receipt_rule(rule)
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ # Makes sure that the chosen bucket has the required policy
53
+ def ensure_s3_bucket_policy()
54
+
55
+ resp = @sts.get_caller_identity({})
56
+ account = resp.to_h[:account]
57
+
58
+ #TODO: Merge existing policies
59
+ policy = {
60
+ :Version => "2008-10-17",
61
+ :Statement => [
62
+ {
63
+ :Sid => "GiveSESPermissionToWriteEmail",
64
+ :Effect => "Allow",
65
+ :Principal => {
66
+ :Service => [
67
+ "ses.amazonaws.com"
68
+ ]
69
+ },
70
+ :Action => [
71
+ "s3:PutObject"
72
+ ],
73
+ :Resource => "arn:aws:s3:::#{@receipt_rule.s3_bucket}/*",
74
+ :Condition => {
75
+ :StringEquals => {
76
+ 'aws:Referer' => account
77
+ }
78
+ }
79
+ }
80
+ ]
81
+ }
82
+
83
+ @s3.put_bucket_policy({
84
+ bucket: @receipt_rule.s3_bucket,
85
+ policy: policy.to_json
86
+ })
87
+ end
88
+
89
+ def ensure_address_domains()
90
+ @receipt_rule.email_addresses.each { |address|
91
+ ensure_address_domain address
92
+ }
93
+ end
94
+
95
+ def ensure_address_domain(address)
96
+ domain = address.split('@').last
97
+
98
+ resp = @route53.list_hosted_zones_by_name({})
99
+ hosted_zones = resp.to_h[:hosted_zones]
100
+ hosted_zone = hosted_zones.find { |s| s[:name] == "#{domain}." }
101
+ unless hosted_zone then
102
+ raise Exception.new("Route53 doesn't contain domain entry for the #{domain}. If you are parking your domain outside AWS, you will need to set the DNS entries yourself")
103
+ end
104
+ resp = @ses.list_identities({
105
+ identity_type: 'Domain'
106
+ })
107
+ identities = resp.to_h[:identities]
108
+ domain_identity = identities.find { |s| s == domain }
109
+ if domain_identity then
110
+ resp = @ses.get_identity_verification_attributes({
111
+ identities: [
112
+ domain,
113
+ ]
114
+ })
115
+ domain_identity = resp.to_h[:verification_attributes][domain]
116
+ unless domain_identity[:verification_status] == 'Success' then
117
+ ensure_route53_hosted_zone_entries(hosted_zone, domain_identity[:verification_token])
118
+ end
119
+ else
120
+ resp = @ses.verify_domain_identity({
121
+ domain: domain,
122
+ })
123
+ verification_token = resp.to_h[:verification_token]
124
+ ensure_route53_hosted_zone_entries(hosted_zone, verification_token)
125
+ end
126
+ end
127
+
128
+ def ensure_route53_hosted_zone_entries(hosted_zone, verification_token)
129
+ request = {
130
+ hosted_zone_id: hosted_zone[:id],
131
+ change_batch: {
132
+ comment: 'Entries required for SES setup',
133
+ changes: [
134
+ {
135
+ action: 'UPSERT',
136
+ resource_record_set: {
137
+ name: hosted_zone[:name],
138
+ type: 'TXT',
139
+ ttl: 300,
140
+ resource_records: [
141
+ {
142
+ value: "\"#{verification_token}\""
143
+ },
144
+ ]
145
+ },
146
+ },
147
+ {
148
+ action: "UPSERT",
149
+ resource_record_set: {
150
+ name: hosted_zone[:name],
151
+ type: 'MX',
152
+ ttl: 300,
153
+ resource_records: [
154
+ {
155
+ value: '10 inbound-smtp.eu-west-1.amazonaws.com'
156
+ }
157
+ ]
158
+ }
159
+ }
160
+ ]
161
+ }
162
+ }
163
+ resp = @route53.change_resource_record_sets(request)
164
+ end
165
+
166
+ # Ensure the chosen rule set exists
167
+ def ensure_rule_set()
168
+ resp = @ses.list_receipt_rule_sets()
169
+ add_new_rule_set = true
170
+ resp.to_h[:rule_sets].each { |rule_set|
171
+ add_new_rule_set = false if (rule_set[:name] =~ /^#{Regexp.escape(@receipt_rule.rule_set_name)}$/)
172
+ }
173
+ @ses.create_receipt_rule_set({rule_set_name: @receipt_rule.rule_set_name}) if add_new_rule_set
174
+ end
175
+
176
+ # Ensure the bucket exists
177
+ def ensure_s3_bucket()
178
+ resp = @s3.list_buckets()
179
+ add_new_bucket = true
180
+ resp.to_h[:buckets].each { |bucket|
181
+ add_new_bucket = false if (bucket[:name] =~ /^#{Regexp.escape(@receipt_rule.s3_bucket)}$/)
182
+ }
183
+ @s3.create_bucket({
184
+ acl: "private",
185
+ bucket: @receipt_rule.s3_bucket,
186
+ create_bucket_configuration: {
187
+ location_constraint: @receipt_rule.region
188
+ }
189
+ }) if add_new_bucket
190
+ end
191
+
192
+ # Execute all the assurances
193
+ def ensure_prerequsites()
194
+
195
+ ensure_rule_set
196
+ ensure_s3_bucket
197
+ ensure_s3_bucket_policy
198
+ ensure_address_domains
199
+
200
+ end
201
+
202
+ end
203
+
204
+ end
@@ -0,0 +1,3 @@
1
+ module Sessel
2
+ VERSION = "0.0.1"
3
+ end
data/sessel.png ADDED
Binary file
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sessel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sessel"
8
+ spec.version = Sessel::VERSION
9
+ spec.authors = ["Rafal Nowosielski"]
10
+ spec.email = ["rafal@nowosielski.email"]
11
+
12
+ spec.summary = "The gem includes a tool to store SES configuration in a scriptable form"
13
+ spec.description = "When writing solutions in the cloud, it is often valuable to have all configuraiton in code. Sonce CloutFormation doesn't support SES, this gem provides a way to store this confiuration in a scriptable form"
14
+ spec.homepage = "https://nowosielski.website"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "bin"
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.13"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest", "~> 5.0"
26
+
27
+ spec.add_runtime_dependency "aws-sdk", "~> 2.6"
28
+ spec.add_runtime_dependency "thor"
29
+ spec.add_runtime_dependency "highline", "2.0.0.pre.develop.6"
30
+
31
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sessel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rafal Nowosielski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aws-sdk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: highline
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0.pre.develop.6
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0.pre.develop.6
97
+ description: When writing solutions in the cloud, it is often valuable to have all
98
+ configuraiton in code. Sonce CloutFormation doesn't support SES, this gem provides
99
+ a way to store this confiuration in a scriptable form
100
+ email:
101
+ - rafal@nowosielski.email
102
+ executables:
103
+ - sessel
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - .gitignore
108
+ - Gemfile
109
+ - LICENSE
110
+ - README.md
111
+ - Rakefile
112
+ - bin/sessel
113
+ - lib/sessel.rb
114
+ - lib/sessel/ask.rb
115
+ - lib/sessel/configuration_set.rb
116
+ - lib/sessel/configuration_set_creator.rb
117
+ - lib/sessel/io.rb
118
+ - lib/sessel/main.rb
119
+ - lib/sessel/receipt_rule.rb
120
+ - lib/sessel/receipt_rule_creator.rb
121
+ - lib/sessel/version.rb
122
+ - sessel.png
123
+ - swaggerless.gemspec
124
+ homepage: https://nowosielski.website
125
+ licenses: []
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.0.14.1
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: The gem includes a tool to store SES configuration in a scriptable form
147
+ test_files: []