fake_sns 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.simplecov +4 -0
- data/.travis.yml +5 -0
- data/Gemfile +2 -0
- data/README.md +167 -0
- data/Rakefile +24 -0
- data/bin/fake_sns +79 -0
- data/config.ru +3 -0
- data/fake_sns.gemspec +34 -0
- data/lib/fake_sns/action.rb +24 -0
- data/lib/fake_sns/actions/create_topic.rb +41 -0
- data/lib/fake_sns/actions/delete_topic.rb +13 -0
- data/lib/fake_sns/actions/get_topic_attributes.rb +32 -0
- data/lib/fake_sns/actions/list_subscriptions.rb +24 -0
- data/lib/fake_sns/actions/list_subscriptions_by_topic.rb +23 -0
- data/lib/fake_sns/actions/list_topics.rb +13 -0
- data/lib/fake_sns/actions/publish.rb +37 -0
- data/lib/fake_sns/actions/set_topic_attributes.rb +19 -0
- data/lib/fake_sns/actions/subscribe.rb +43 -0
- data/lib/fake_sns/database.rb +76 -0
- data/lib/fake_sns/deliver_message.rb +100 -0
- data/lib/fake_sns/error.rb +34 -0
- data/lib/fake_sns/error_response.rb +46 -0
- data/lib/fake_sns/message.rb +28 -0
- data/lib/fake_sns/message_collection.rb +40 -0
- data/lib/fake_sns/response.rb +16 -0
- data/lib/fake_sns/server.rb +76 -0
- data/lib/fake_sns/show_output.rb +20 -0
- data/lib/fake_sns/storage.rb +75 -0
- data/lib/fake_sns/subscription.rb +17 -0
- data/lib/fake_sns/subscription_collection.rb +34 -0
- data/lib/fake_sns/test_integration.rb +110 -0
- data/lib/fake_sns/topic.rb +13 -0
- data/lib/fake_sns/topic_collection.rb +41 -0
- data/lib/fake_sns/version.rb +3 -0
- data/lib/fake_sns/views/create_topic.xml.erb +8 -0
- data/lib/fake_sns/views/delete_topic.xml.erb +5 -0
- data/lib/fake_sns/views/error.xml.erb +8 -0
- data/lib/fake_sns/views/get_topic_attributes.xml.erb +15 -0
- data/lib/fake_sns/views/list_subscriptions.xml.erb +18 -0
- data/lib/fake_sns/views/list_subscriptions_by_topic.xml.erb +18 -0
- data/lib/fake_sns/views/list_topics.xml.erb +14 -0
- data/lib/fake_sns/views/publish.xml.erb +8 -0
- data/lib/fake_sns/views/set_topic_attributes.xml.erb +5 -0
- data/lib/fake_sns/views/subscribe.xml.erb +8 -0
- data/lib/fake_sns.rb +51 -0
- data/spec/fake_sns/drain_spec.rb +91 -0
- data/spec/fake_sns/publish_spec.rb +28 -0
- data/spec/fake_sns/replace_spec.rb +14 -0
- data/spec/fake_sns/subscribing_spec.rb +42 -0
- data/spec/fake_sns/topics_spec.rb +44 -0
- data/spec/spec_helper.rb +54 -0
- metadata +271 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eea380f4afe8a28a3fe8ef442ee68bc36ed44fc7
|
4
|
+
data.tar.gz: 27394ec000f0bb22a985f37e38058c9c32057b33
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4a4c3f9cb1e0e99c47fc939ba45bf15ce944ab3bdc9ac70f3086daccfd1e0ba5c8b1e7a3ceed9a360653d3ae614ac5bf3f83bf8e519f373f3ec5e5c688ce0271
|
7
|
+
data.tar.gz: 65744967afec469a3224a608dd141d5c2549f482e28c1d42f2980388cccfe3e1d37d3ee6714d4ae497c2f337c534780a0bc4621d42cbf182c4cb7eaa7c9a827c
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.simplecov
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
# Fake SNS
|
2
|
+
|
3
|
+
A small web app for local SNS development.
|
4
|
+
|
5
|
+
It contains a small store to inspect, and some methods to inspect and change the
|
6
|
+
contents, so you can create scenarios.
|
7
|
+
|
8
|
+
### Noteworthy differences:
|
9
|
+
|
10
|
+
* No checking of access keys.
|
11
|
+
* Returns all topics, not just 100, no support for `NextToken` parameter.
|
12
|
+
|
13
|
+
### Implemented:
|
14
|
+
|
15
|
+
* CreateTopic
|
16
|
+
* ListTopics
|
17
|
+
* DeleteTopic
|
18
|
+
* GetTopicAttributes
|
19
|
+
* SetTopicAttributes
|
20
|
+
* ListSubscriptions
|
21
|
+
* ListSubscriptionsByTopic
|
22
|
+
|
23
|
+
### Under Construction
|
24
|
+
|
25
|
+
* Subscribe
|
26
|
+
* Publish
|
27
|
+
|
28
|
+
### Actions to be implemented:
|
29
|
+
|
30
|
+
* AddPermission
|
31
|
+
* ConfirmSubscription
|
32
|
+
* CreatePlatformApplication
|
33
|
+
* CreatePlatformEndpoint
|
34
|
+
* DeleteEndpoint
|
35
|
+
* DeletePlatformApplication
|
36
|
+
* GetEndpointAttributes
|
37
|
+
* GetPlatformApplicationAttributes
|
38
|
+
* GetSubscriptionAttributes
|
39
|
+
* ListEndpointsByPlatformApplication
|
40
|
+
* ListPlatformApplications
|
41
|
+
* RemovePermission
|
42
|
+
* SetEndpointAttributes
|
43
|
+
* SetPlatformApplicationAttributes
|
44
|
+
* SetSubscriptionAttributes
|
45
|
+
* Unsubscribe
|
46
|
+
|
47
|
+
## Usage
|
48
|
+
|
49
|
+
There are 2 ways of running FakeSNS, as a gem, or as plain Rack app. The first
|
50
|
+
is easy, the latter is more flexible.
|
51
|
+
|
52
|
+
As a gem:
|
53
|
+
|
54
|
+
```
|
55
|
+
$ gem install fake_sns
|
56
|
+
$ fake_sns -p 9292
|
57
|
+
```
|
58
|
+
|
59
|
+
To configure AWS-SDK to send messages here:
|
60
|
+
|
61
|
+
``` ruby
|
62
|
+
AWS.config(
|
63
|
+
use_ssl: false,
|
64
|
+
sns_endpoint: "0.0.0.0",
|
65
|
+
sns_port: 9292,
|
66
|
+
)
|
67
|
+
```
|
68
|
+
|
69
|
+
### Command line options
|
70
|
+
|
71
|
+
Get help by running `fake_sns --help`. These options are basically the same as
|
72
|
+
Sinatra's options. Here are the SNS specific options:
|
73
|
+
|
74
|
+
* Store the database somewhere else: `--database FILENAME` or
|
75
|
+
specify an in memory database that will be lost: `--database :memory:`
|
76
|
+
|
77
|
+
### Extra endpoints
|
78
|
+
|
79
|
+
To get a YAML representation of all the data known to FakeSNS, do a GET request
|
80
|
+
to the root path:
|
81
|
+
|
82
|
+
```
|
83
|
+
curl -X GET http://localhost:9292/
|
84
|
+
```
|
85
|
+
|
86
|
+
To change the database, submit the contents you got from the previous step,
|
87
|
+
augment it and submit it as the body of a PUT request:
|
88
|
+
|
89
|
+
```
|
90
|
+
curl -X GET http://localhost:9292/ -o my-data.yml
|
91
|
+
vim my-data.yml
|
92
|
+
curl -X PUT --data @my-data.yml http://localhost:9292/
|
93
|
+
```
|
94
|
+
|
95
|
+
To reset the entire database, send a DELETE request:
|
96
|
+
|
97
|
+
```
|
98
|
+
curl -X DELETE http://localhost:9292/
|
99
|
+
```
|
100
|
+
|
101
|
+
To send ALL the messages stored in the queue, you can send a post request:
|
102
|
+
|
103
|
+
```
|
104
|
+
curl -X POST http://localhost:9292/drain
|
105
|
+
```
|
106
|
+
|
107
|
+
You can also just send a single message:
|
108
|
+
|
109
|
+
```
|
110
|
+
curl -X POST http://localhost:9292/drain/:message_id
|
111
|
+
```
|
112
|
+
|
113
|
+
Currently, only HTTP/HTTPS and SQS endpoints are working. You'll need
|
114
|
+
to pass AWS config (in JSON format) for the SQS integration to work. See
|
115
|
+
[FakeSNS] [fake_sns] for more information.
|
116
|
+
|
117
|
+
```
|
118
|
+
curl \
|
119
|
+
-X POST \
|
120
|
+
--data '{"aws_config": {"use_ssl": false, "sqs_endpoint": "localhost", "sqs_port": 4789, "secret_access_key": "xxx", "access_key_id": "yyy"}}' \
|
121
|
+
http://localhost:9292/drain
|
122
|
+
```
|
123
|
+
|
124
|
+
### Test Integration
|
125
|
+
|
126
|
+
When making integration tests for your app, you can easily include Fake SNS.
|
127
|
+
|
128
|
+
Here are the methods you need to run FakeSNS programmatically.
|
129
|
+
|
130
|
+
``` ruby
|
131
|
+
require "fake_sns/test_integration"
|
132
|
+
|
133
|
+
# globally, before the test suite starts:
|
134
|
+
AWS.config(
|
135
|
+
use_ssl: false,
|
136
|
+
sns_endpoint: "localhost",
|
137
|
+
sns_port: 4568,
|
138
|
+
access_key_id: "fake access key",
|
139
|
+
secret_access_key: "fake secret key",
|
140
|
+
)
|
141
|
+
fake_sns = FakeSNS::TestIntegration.new
|
142
|
+
|
143
|
+
# before each test that requires SNS:
|
144
|
+
fake_sns.start
|
145
|
+
|
146
|
+
# at the end of the suite:
|
147
|
+
at_exit {
|
148
|
+
fake_sns.stop
|
149
|
+
}
|
150
|
+
|
151
|
+
# for debugging, get everything FakeSNS knows:
|
152
|
+
puts fake_sns.data.inspect
|
153
|
+
|
154
|
+
# if you have SQS configured in the AWS config, you can also do:
|
155
|
+
fake_sns.drain
|
156
|
+
```
|
157
|
+
|
158
|
+
See `spec/spec_helper.rb` in this project for an example on how to load it in
|
159
|
+
your test suite.
|
160
|
+
|
161
|
+
## More information
|
162
|
+
|
163
|
+
* [API Reference](http://docs.aws.amazon.com/sns/latest/api/API_Operations.html)
|
164
|
+
* [AWS-SDK docs](http://rubydoc.info/gems/aws-sdk/frames)
|
165
|
+
* [Fake SQS] [fake_sqs]
|
166
|
+
|
167
|
+
[fake_sqs]: https://github.com/iain/fake_sqs
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require "tempfile"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
namespace :spec do
|
7
|
+
|
8
|
+
desc "Run specs with in-memory database"
|
9
|
+
RSpec::Core::RakeTask.new(:memory) do |t|
|
10
|
+
ENV["SNS_DATABASE"] = ":memory:"
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Run specs with file database"
|
14
|
+
RSpec::Core::RakeTask.new(:file) do |t|
|
15
|
+
file = Tempfile.new(["rspec-sns", ".yml"], encoding: "utf-8")
|
16
|
+
ENV["SNS_DATABASE"] = file.path
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Run spec suite with both in-memory and file"
|
22
|
+
task :spec => ["spec:memory", "spec:file"]
|
23
|
+
|
24
|
+
task :default => :spec
|
data/bin/fake_sns
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path("../../lib", __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'fake_sns'
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
options = {
|
10
|
+
:port => 9292,
|
11
|
+
:host => "0.0.0.0",
|
12
|
+
:verbose => false,
|
13
|
+
:daemonize => false,
|
14
|
+
:database => nil,
|
15
|
+
}
|
16
|
+
|
17
|
+
parser = OptionParser.new do |o|
|
18
|
+
|
19
|
+
o.on "--database FILENAME", "Place to store the database (defaults to ~/.fake_sns.yml)" do |filename|
|
20
|
+
options[:database] = filename
|
21
|
+
end
|
22
|
+
|
23
|
+
o.on "-p", "--port PORT", Integer, "Port to use (default: #{options[:port]})" do |port|
|
24
|
+
options[:port] = port
|
25
|
+
end
|
26
|
+
|
27
|
+
o.on "-o", "--bind HOST", "Host to bind to (default: 0.0.0.0)" do |host|
|
28
|
+
options[:host] = host
|
29
|
+
end
|
30
|
+
|
31
|
+
o.on "-s", "--server SERVER", ['thin', 'mongrel', 'webrick'], "Server to use: thin, mongrel or webrick (by default Sinatra chooses the best available)" do |server|
|
32
|
+
options[:server] = server
|
33
|
+
end
|
34
|
+
|
35
|
+
o.on "-P", "--pid PIDFILE", "Where to write the pid" do |pid|
|
36
|
+
options[:pid] = pid
|
37
|
+
end
|
38
|
+
|
39
|
+
o.on "-d", "--[no-]daemonize", "Detaches the process" do |daemonize|
|
40
|
+
options[:daemonize] = daemonize
|
41
|
+
end
|
42
|
+
|
43
|
+
o.on "-v", "--[no]-verbose", "Shows input parameters and output XML" do |verbose|
|
44
|
+
options[:verbose] = verbose
|
45
|
+
end
|
46
|
+
|
47
|
+
o.on_tail "--version", "Shows the version" do
|
48
|
+
puts "fake_sns version #{FakeSNS::VERSION}"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
o.on_tail "-h", "--help", "Shows this help page" do
|
53
|
+
puts o
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
parser.parse!
|
60
|
+
|
61
|
+
if options[:daemonize]
|
62
|
+
Process.daemon(true, true)
|
63
|
+
end
|
64
|
+
|
65
|
+
if (pid = options[:pid])
|
66
|
+
if File.exist?(pid)
|
67
|
+
existing_pid = File.open(pid, 'r').read.chomp.to_i
|
68
|
+
running = Process.getpgid(existing_pid) rescue false
|
69
|
+
if running
|
70
|
+
warn "Error, Process #{existing_pid} already running"
|
71
|
+
exit 1
|
72
|
+
else
|
73
|
+
warn "Cleaning up stale pid at #{pid}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
File.open(pid, 'w') { |f| f.write(Process.pid) }
|
77
|
+
end
|
78
|
+
|
79
|
+
FakeSNS.server(options).run!
|
data/config.ru
ADDED
data/fake_sns.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fake_sns/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fake_sns"
|
8
|
+
spec.version = FakeSNS::VERSION
|
9
|
+
spec.authors = ["iain"]
|
10
|
+
spec.email = ["iain@iain.nl"]
|
11
|
+
spec.description = %q{Small Fake version of SNS}
|
12
|
+
spec.summary = %q{Small Fake version of SNS}
|
13
|
+
spec.homepage = "https://github.com/yourkarma/fake_sns"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "sinatra", "~> 1.4"
|
21
|
+
spec.add_dependency "virtus", "~> 1.0"
|
22
|
+
spec.add_dependency "verbose_hash_fetch"
|
23
|
+
spec.add_dependency "faraday", "~> 0.8"
|
24
|
+
spec.add_dependency "aws-sdk", "~> 1.30"
|
25
|
+
|
26
|
+
spec.add_development_dependency "aws-sdk"
|
27
|
+
spec.add_development_dependency "bundler"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
spec.add_development_dependency "pry"
|
31
|
+
spec.add_development_dependency "fake_sqs", "~> 0.0.9"
|
32
|
+
spec.add_development_dependency "json_expressions"
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
class Action
|
3
|
+
|
4
|
+
attr_reader :db, :params
|
5
|
+
|
6
|
+
def self.param(fields, &block)
|
7
|
+
fields.each do |field, key|
|
8
|
+
define_method field do
|
9
|
+
params.fetch(key, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(db, params)
|
15
|
+
@db = db
|
16
|
+
@params = params
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
# override me, if needed
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class CreateTopic < Action
|
4
|
+
|
5
|
+
param name: "Name"
|
6
|
+
|
7
|
+
def valid_name?
|
8
|
+
name =~ /\A[\w\-]+\z/
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise InvalidParameterValue, "Topic Name: #{name.inspect}" unless valid_name?
|
13
|
+
@topic = (existing_topic || new_topic)
|
14
|
+
end
|
15
|
+
|
16
|
+
def arn
|
17
|
+
topic["arn"]
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :topic
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def new_topic
|
25
|
+
arn = generate_arn
|
26
|
+
topic_attributes = { "arn" => arn, "name" => name }
|
27
|
+
db.topics.create(topic_attributes)
|
28
|
+
topic_attributes
|
29
|
+
end
|
30
|
+
|
31
|
+
def generate_arn
|
32
|
+
"arn:aws:sns:us-east-1:#{SecureRandom.hex}:#{name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def existing_topic
|
36
|
+
db.topics.find { |t| t["name"] == name }
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class GetTopicAttributes < Action
|
4
|
+
|
5
|
+
param arn: "TopicArn"
|
6
|
+
|
7
|
+
# TopicArn
|
8
|
+
# Owner
|
9
|
+
# Policy
|
10
|
+
# DisplayName
|
11
|
+
# SubscriptionsPending
|
12
|
+
# SubscriptionsConfirmed
|
13
|
+
# SubscriptionsDeleted
|
14
|
+
# DeliveryPolicy
|
15
|
+
# EffectiveDeliveryPolicy
|
16
|
+
|
17
|
+
attr_reader :topic
|
18
|
+
|
19
|
+
def call
|
20
|
+
@topic = db.topics.fetch(arn) { raise NotFound, arn }
|
21
|
+
end
|
22
|
+
|
23
|
+
def each_attribute
|
24
|
+
yield "TopicArn", arn
|
25
|
+
%w(DisplayName Policy DeliveryPolicy).each do |key|
|
26
|
+
yield key, topic[key] if topic.has_key?(key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class ListSubscriptions < Action
|
4
|
+
|
5
|
+
param next_token: "NextToken"
|
6
|
+
|
7
|
+
def call
|
8
|
+
end
|
9
|
+
|
10
|
+
def each_subscription
|
11
|
+
subscriptions.each do |subscription|
|
12
|
+
yield subscription
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def subscriptions
|
19
|
+
db.subscriptions
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class ListSubscriptionsByTopic < ListSubscriptions
|
4
|
+
|
5
|
+
param topic_arn: "TopicArn"
|
6
|
+
param next_token: "NextToken"
|
7
|
+
|
8
|
+
def call
|
9
|
+
super
|
10
|
+
@topic = db.topics.fetch(topic_arn) do
|
11
|
+
raise InvalidParameterValue, "Unknown topic: #{topic_arn}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def subscriptions
|
18
|
+
super.select { |s| s["topic_arn"] == topic_arn }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class Publish < Action
|
4
|
+
|
5
|
+
param message: "Message"
|
6
|
+
param message_structure: "MessageStructure"
|
7
|
+
param subject: "Subject" do nil end
|
8
|
+
param target_arn: "TargetArn" do nil end
|
9
|
+
param topic_arn: "TopicArn" do nil end
|
10
|
+
|
11
|
+
def call
|
12
|
+
if (bytes = message.bytesize) > 262144
|
13
|
+
raise InvalidParameterValue, "Too much bytes: #{bytes} > 262144."
|
14
|
+
end
|
15
|
+
@topic = db.topics.fetch(topic_arn) do
|
16
|
+
raise InvalidParameterValue, "Unknown topic: #{topic_arn}"
|
17
|
+
end
|
18
|
+
@message_id = SecureRandom.uuid
|
19
|
+
|
20
|
+
db.messages.create(
|
21
|
+
id: message_id,
|
22
|
+
subject: subject,
|
23
|
+
message: message,
|
24
|
+
topic_arn: topic_arn,
|
25
|
+
structure: message_structure,
|
26
|
+
target_arn: target_arn,
|
27
|
+
received_at: Time.now,
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def message_id
|
32
|
+
@message_id || raise(InternalFailure, "no message id yet, this should not happen")
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class SetTopicAttributes < Action
|
4
|
+
|
5
|
+
VALID_PARAMETER_NAMES = %w(Policy DisplayName DeliveryPolicy)
|
6
|
+
|
7
|
+
param key: "AttributeName"
|
8
|
+
param value: "AttributeValue"
|
9
|
+
param arn: "TopicArn"
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise InvalidParameterValue, "AttributeName: #{key.inspect}" unless VALID_PARAMETER_NAMES.include?(key)
|
13
|
+
topic = db.topics.fetch(arn) { raise NotFound, arn }
|
14
|
+
topic[key] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
module Actions
|
3
|
+
class Subscribe < Action
|
4
|
+
|
5
|
+
param endpoint: "Endpoint"
|
6
|
+
param protocol: "Protocol"
|
7
|
+
param topic_arn: "TopicArn"
|
8
|
+
|
9
|
+
attr_reader :topic
|
10
|
+
|
11
|
+
def call
|
12
|
+
@topic = db.topics.fetch(topic_arn) do
|
13
|
+
raise InvalidParameterValue, "Unknown topic: #{topic_arn}"
|
14
|
+
end
|
15
|
+
@subscription = (existing_subscription || new_subscription)
|
16
|
+
end
|
17
|
+
|
18
|
+
def subscription_arn
|
19
|
+
@subscription["arn"]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def existing_subscription
|
25
|
+
db.subscriptions.to_a.find { |s|
|
26
|
+
s.topic_arn == topic_arn && s.endpoint == endpoint
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def new_subscription
|
31
|
+
attributes = {
|
32
|
+
"arn" => "#{topic_arn}:#{SecureRandom.uuid}",
|
33
|
+
"protocol" => protocol,
|
34
|
+
"endpoint" => endpoint,
|
35
|
+
"topic_arn" => topic_arn,
|
36
|
+
}
|
37
|
+
db.subscriptions.create(attributes)
|
38
|
+
attributes
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|