simple_deploy 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG.md +6 -0
  3. data/lib/simple_deploy/aws/cloud_formation/error.rb +32 -0
  4. data/lib/simple_deploy/aws/cloud_formation.rb +76 -0
  5. data/lib/simple_deploy/aws/instance_reader.rb +59 -0
  6. data/lib/simple_deploy/aws/simpledb.rb +52 -0
  7. data/lib/simple_deploy/aws.rb +4 -0
  8. data/lib/simple_deploy/cli/attributes.rb +7 -18
  9. data/lib/simple_deploy/cli/clone.rb +9 -19
  10. data/lib/simple_deploy/cli/create.rb +5 -14
  11. data/lib/simple_deploy/cli/deploy.rb +8 -11
  12. data/lib/simple_deploy/cli/destroy.rb +4 -10
  13. data/lib/simple_deploy/cli/environments.rb +1 -1
  14. data/lib/simple_deploy/cli/events.rb +5 -11
  15. data/lib/simple_deploy/cli/execute.rb +6 -9
  16. data/lib/simple_deploy/cli/instances.rb +4 -9
  17. data/lib/simple_deploy/cli/list.rb +5 -10
  18. data/lib/simple_deploy/cli/outputs.rb +5 -11
  19. data/lib/simple_deploy/cli/parameters.rb +5 -11
  20. data/lib/simple_deploy/cli/protect.rb +5 -10
  21. data/lib/simple_deploy/cli/resources.rb +5 -11
  22. data/lib/simple_deploy/cli/shared.rb +6 -6
  23. data/lib/simple_deploy/cli/status.rb +5 -11
  24. data/lib/simple_deploy/cli/template.rb +8 -13
  25. data/lib/simple_deploy/cli/update.rb +6 -10
  26. data/lib/simple_deploy/configuration.rb +102 -0
  27. data/lib/simple_deploy/entry.rb +71 -0
  28. data/lib/simple_deploy/entry_lister.rb +30 -0
  29. data/lib/simple_deploy/exceptions.rb +8 -0
  30. data/lib/simple_deploy/misc/attribute_merger.rb +2 -5
  31. data/lib/simple_deploy/notifier/campfire.rb +15 -12
  32. data/lib/simple_deploy/notifier.rb +6 -11
  33. data/lib/simple_deploy/stack/deployment/status.rb +5 -3
  34. data/lib/simple_deploy/stack/deployment.rb +8 -10
  35. data/lib/simple_deploy/stack/execute.rb +2 -3
  36. data/lib/simple_deploy/stack/output_mapper.rb +1 -4
  37. data/lib/simple_deploy/stack/ssh.rb +4 -4
  38. data/lib/simple_deploy/stack/{stack_attribute_formater.rb → stack_attribute_formatter.rb} +4 -6
  39. data/lib/simple_deploy/stack/stack_creator.rb +46 -0
  40. data/lib/simple_deploy/stack/stack_destroyer.rb +19 -0
  41. data/lib/simple_deploy/stack/stack_formatter.rb +25 -0
  42. data/lib/simple_deploy/stack/stack_lister.rb +18 -0
  43. data/lib/simple_deploy/stack/stack_reader.rb +56 -0
  44. data/lib/simple_deploy/stack/stack_updater.rb +67 -0
  45. data/lib/simple_deploy/stack/status.rb +53 -0
  46. data/lib/simple_deploy/stack.rb +89 -37
  47. data/lib/simple_deploy/version.rb +1 -1
  48. data/lib/simple_deploy.rb +31 -1
  49. data/simple_deploy.gemspec +6 -3
  50. data/spec/aws/cloud_formation/error_spec.rb +50 -0
  51. data/spec/aws/cloud_formation_spec.rb +207 -0
  52. data/spec/aws/instance_reader_spec.rb +96 -0
  53. data/spec/aws/simpledb_spec.rb +89 -0
  54. data/spec/cli/attributes_spec.rb +5 -15
  55. data/spec/cli/clone_spec.rb +14 -27
  56. data/spec/cli/create_spec.rb +11 -18
  57. data/spec/cli/deploy_spec.rb +24 -63
  58. data/spec/cli/destroy_spec.rb +7 -25
  59. data/spec/cli/outputs_spec.rb +12 -17
  60. data/spec/cli/protect_spec.rb +68 -106
  61. data/spec/cli/shared_spec.rb +12 -15
  62. data/spec/cli/update_spec.rb +9 -27
  63. data/spec/config_spec.rb +47 -14
  64. data/spec/contexts/config_contexts.rb +28 -0
  65. data/spec/contexts/logger_contexts.rb +9 -0
  66. data/spec/contexts/stack_contexts.rb +40 -0
  67. data/spec/entry_lister_spec.rb +31 -0
  68. data/spec/entry_spec.rb +86 -0
  69. data/spec/misc/attribute_merger_spec.rb +3 -8
  70. data/spec/notifier/campfire_spec.rb +21 -61
  71. data/spec/notifier_spec.rb +18 -40
  72. data/spec/spec_helper.rb +10 -0
  73. data/spec/stack/deployment/status_spec.rb +13 -13
  74. data/spec/stack/deployment_spec.rb +26 -21
  75. data/spec/stack/execute_spec.rb +7 -3
  76. data/spec/stack/output_mapper_spec.rb +3 -15
  77. data/spec/stack/ssh_spec.rb +14 -13
  78. data/spec/stack/{stack_attribute_formater_spec.rb → stack_attribute_formatter_spec.rb} +19 -16
  79. data/spec/stack/stack_creator_spec.rb +46 -0
  80. data/spec/stack/stack_destroyer_spec.rb +18 -0
  81. data/spec/stack/stack_formatter_spec.rb +37 -0
  82. data/spec/stack/stack_lister_spec.rb +17 -0
  83. data/spec/stack/stack_reader_spec.rb +81 -0
  84. data/spec/stack/stack_updater_spec.rb +79 -0
  85. data/spec/stack/status_spec.rb +106 -0
  86. data/spec/stack_spec.rb +160 -133
  87. metadata +112 -19
  88. data/.rvmrc +0 -1
  89. data/lib/simple_deploy/config.rb +0 -87
@@ -1,3 +1,3 @@
1
1
  module SimpleDeploy
2
- VERSION = "0.7.2"
2
+ VERSION = "0.7.3"
3
3
  end
data/lib/simple_deploy.rb CHANGED
@@ -1,6 +1,9 @@
1
+ require 'simple_deploy/aws'
1
2
  require 'simple_deploy/env'
3
+ require 'simple_deploy/entry'
4
+ require 'simple_deploy/entry_lister'
2
5
  require 'simple_deploy/exceptions'
3
- require 'simple_deploy/config'
6
+ require 'simple_deploy/configuration'
4
7
  require 'simple_deploy/artifact'
5
8
  require 'simple_deploy/stack'
6
9
  require 'simple_deploy/misc'
@@ -9,3 +12,30 @@ require 'simple_deploy/notifier'
9
12
  require 'simple_deploy/logger'
10
13
  require 'simple_deploy/version'
11
14
  require 'simple_deploy/backoff'
15
+
16
+ module SimpleDeploy
17
+ module_function
18
+
19
+ def create_config(environment, custom_config = {})
20
+ raise SimpleDeploy::Exceptions::IllegalStateException.new(
21
+ 'environment is not defined') unless environment
22
+
23
+ @config = SimpleDeploy::Configuration.configure environment, custom_config
24
+ end
25
+
26
+ def config
27
+ @config
28
+ end
29
+
30
+ def release_config
31
+ @config = nil
32
+ end
33
+
34
+ def environments(custom_config = {})
35
+ SimpleDeploy::Configuration.environments custom_config
36
+ end
37
+
38
+ def logger(log_level = 'info')
39
+ @logger ||= SimpleDeployLogger.new :log_level => log_level
40
+ end
41
+ end
@@ -20,10 +20,13 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_development_dependency "fakefs", "~> 0.4.2"
22
22
  s.add_development_dependency "rake"
23
- s.add_development_dependency "rspec", "~> 2.11.0"
23
+ s.add_development_dependency "rspec", "~> 2.13.0"
24
+ s.add_development_dependency "simplecov", "~> 0.7.1"
25
+ s.add_development_dependency "timecop", "~> 0.6.1"
24
26
 
25
27
  s.add_runtime_dependency "capistrano", "= 2.13.5"
26
- s.add_runtime_dependency "stackster", '= 0.4.4'
27
- s.add_runtime_dependency "tinder", "= 1.8.0"
28
+ s.add_runtime_dependency "esbit", "~> 0.0.4"
28
29
  s.add_runtime_dependency "trollop", "= 2.0"
30
+ s.add_runtime_dependency "fog", "= 1.10.0"
31
+ s.add_runtime_dependency "xml-simple", "= 1.1.2"
29
32
  end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::AWS::CloudFormation::Error do
4
+ include_context 'double stubbed config', :access_key => 'key',
5
+ :secret_key => 'XXX',
6
+ :region => 'us-west-1'
7
+ include_context 'double stubbed logger'
8
+
9
+ before do
10
+ @exception_stub1 = stub 'Excon::Response'
11
+ @exception_stub1.stub(:response).and_return(@exception_stub1)
12
+ @exception_stub1.stub(:body).and_return('<opt><Error><Message>No updates are to be performed.</Message></Error></opt>')
13
+
14
+ @exception_stub2 = stub 'Excon::Response'
15
+ @exception_stub2.stub(:response).and_return(@exception_stub2)
16
+ @exception_stub2.stub(:body).and_return('<opt><Error><Message>Oops.</Message></Error></opt>')
17
+
18
+ @exception_stub3 = stub 'Excon::Response'
19
+ @exception_stub3.stub(:response).and_return(@exception_stub3)
20
+ @exception_stub3.stub(:body).and_return('<opt><Error><Message>Stack:test does not exist</Message></Error></opt>')
21
+ end
22
+
23
+ describe 'process' do
24
+ it 'should process no update messages' do
25
+ error = SimpleDeploy::AWS::CloudFormation::Error.new :exception => @exception_stub1
26
+ expect { error.process }.to_not raise_error SimpleDeploy::Exceptions::CloudFormationError
27
+ end
28
+
29
+ it 'should re-raise unkonwn errors as SimpleDeploy::CloudFormationError' do
30
+ error = SimpleDeploy::AWS::CloudFormation::Error.new :exception => @exception_stub2
31
+
32
+ lambda { error.process }.should raise_error SimpleDeploy::Exceptions::CloudFormationError
33
+ end
34
+
35
+ it 'should re-raise unkonwn errors as SimpleDeploy::CloudFormationError and set mesg' do
36
+ error = SimpleDeploy::AWS::CloudFormation::Error.new :exception => @exception_stub2
37
+ begin
38
+ error.process
39
+ rescue SimpleDeploy::Exceptions::CloudFormationError => e
40
+ e.message.should == "Oops."
41
+ end
42
+ end
43
+
44
+ it 'should reaise stck unkown messages as SimpleDeploy::UnknownStack' do
45
+ error = SimpleDeploy::AWS::CloudFormation::Error.new :exception => @exception_stub3
46
+ lambda { error.process }.should raise_error SimpleDeploy::Exceptions::UnknownStack
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,207 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::AWS::CloudFormation do
4
+ include_context 'double stubbed config', :access_key => 'key',
5
+ :secret_key => 'XXX',
6
+ :region => 'us-west-1'
7
+ include_context 'double stubbed logger'
8
+
9
+ before do
10
+ @error_stub = stub 'Error', :process => 'Processed Error'
11
+ @response_stub = stub 'Excon::Response', :body => {
12
+ 'Stacks' => [{'StackStatus' => 'green', 'Outputs' => [{'key' => 'value'}]}],
13
+ 'StackResources' => [{'StackName' => 'my_stack'}],
14
+ 'StackEvents' => ['event1', 'event2'],
15
+ 'TemplateBody' => '{EIP: "string"}'
16
+ }
17
+
18
+ @cf_mock = mock 'CloudFormation'
19
+ Fog::AWS::CloudFormation.stub(:new).and_return(@cf_mock)
20
+
21
+ @args = {
22
+ :parameters => { 'parameter1' => 'my_param' },
23
+ :name => 'my_stack',
24
+ :template => 'my_template'
25
+ }
26
+
27
+ @exception = Exception.new('Failed')
28
+
29
+ @cf = SimpleDeploy::AWS::CloudFormation.new
30
+ end
31
+
32
+ after do
33
+ SimpleDeploy.release_config
34
+ end
35
+
36
+ describe "create" do
37
+ it "should create the stack on Cloud Formation" do
38
+ @cf_mock.should_receive(:create_stack).with('my_stack',
39
+ { 'Capabilities' => ['CAPABILITY_IAM'],
40
+ 'TemplateBody' => 'my_template',
41
+ 'Parameters' => { 'parameter1' => 'my_param' }
42
+ })
43
+
44
+ @cf.create(@args)
45
+ end
46
+
47
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
48
+ @cf_mock.should_receive(:create_stack).with('my_stack',
49
+ { 'Capabilities' => ['CAPABILITY_IAM'],
50
+ 'TemplateBody' => 'my_template',
51
+ 'Parameters' => { 'parameter1' => 'my_param' }
52
+ }).and_raise(@exception)
53
+
54
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
55
+ with(:exception => @exception).
56
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
57
+
58
+ lambda { @cf.create @args }.
59
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
60
+ end
61
+ end
62
+
63
+ describe "update" do
64
+ it "should update the stack on Cloud Formation" do
65
+ @cf_mock.should_receive(:update_stack).with('my_stack',
66
+ { 'Capabilities' => ['CAPABILITY_IAM'],
67
+ 'TemplateBody' => 'my_template',
68
+ 'Parameters' => { 'parameter1' => 'my_param' }
69
+ })
70
+
71
+ @cf.update(@args)
72
+ end
73
+
74
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
75
+ @cf_mock.should_receive(:update_stack).with('my_stack',
76
+ { 'Capabilities' => ['CAPABILITY_IAM'],
77
+ 'TemplateBody' => 'my_template',
78
+ 'Parameters' => { 'parameter1' => 'my_param' }
79
+ }).and_raise(@exception)
80
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
81
+ with(:exception => @exception).
82
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
83
+
84
+ lambda { @cf.update(@args) }.
85
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
86
+ end
87
+ end
88
+
89
+
90
+ describe 'destroy' do
91
+ it "should delete the stack on Cloud Formation" do
92
+ @cf_mock.should_receive(:delete_stack).with('my_stack')
93
+
94
+ @cf.destroy('my_stack')
95
+ end
96
+
97
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
98
+ @cf_mock.should_receive(:delete_stack).
99
+ with('my_stack').
100
+ and_raise @exception
101
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
102
+ with(:exception => @exception).
103
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
104
+
105
+ lambda { @cf.destroy('my_stack') }.
106
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
107
+ end
108
+ end
109
+
110
+
111
+ describe 'describe_stack' do
112
+ it "should return the Cloud Formation description of the stack" do
113
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_return(@response_stub)
114
+
115
+ @cf.describe_stack('my_stack').should == [{'StackStatus' => 'green', 'Outputs' => [{'key' => 'value'}]}]
116
+ end
117
+
118
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
119
+ @cf_mock.should_receive(:describe_stacks).
120
+ with('StackName' => 'my_stack').
121
+ and_raise @exception
122
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
123
+ with(:exception => @exception).
124
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
125
+
126
+ lambda { @cf.describe_stack('my_stack') }.
127
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
128
+ end
129
+ end
130
+
131
+ describe "stack_resources" do
132
+ it "should return the Cloud Formation description of the stack resources" do
133
+ @cf_mock.should_receive(:describe_stack_resources).with('StackName' => 'my_stack').and_return(@response_stub)
134
+
135
+ @cf.stack_resources('my_stack').should == [{'StackName' => 'my_stack'}]
136
+ end
137
+
138
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
139
+ @cf_mock.should_receive(:describe_stack_resources).
140
+ with('StackName' => 'my_stack').
141
+ and_raise @exception
142
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
143
+ with(:exception => @exception).
144
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
145
+
146
+ lambda { @cf.stack_resources('my_stack') }.
147
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
148
+ end
149
+ end
150
+
151
+ describe "stack_events" do
152
+ it "should return the Cloud Formation description of the stack events" do
153
+ @cf_mock.should_receive(:describe_stack_events).with('my_stack').and_return(@response_stub)
154
+
155
+ @cf.stack_events('my_stack', 2).should == ['event1', 'event2']
156
+ end
157
+
158
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
159
+ @cf_mock.should_receive(:describe_stack_events).
160
+ with('my_stack').
161
+ and_raise @exception
162
+
163
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
164
+ with(:exception => @exception).
165
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
166
+
167
+ lambda { @cf.stack_events('my_stack', 2) }.
168
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
169
+ end
170
+ end
171
+
172
+ describe "stack_status" do
173
+ it "should return the Cloud Formation status of the stack" do
174
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_return(@response_stub)
175
+
176
+ @cf.stack_status('my_stack').should == 'green'
177
+ end
178
+ end
179
+
180
+ describe "stack_outputs" do
181
+ it "should return the Cloud Formation outputs for the stack" do
182
+ @cf_mock.should_receive(:describe_stacks).with('StackName' => 'my_stack').and_return(@response_stub)
183
+
184
+ @cf.stack_outputs('my_stack').should == [{'key' => 'value'}]
185
+ end
186
+ end
187
+
188
+ describe "template" do
189
+ it "should return the Cloud Formation template for the stack" do
190
+ @cf_mock.should_receive(:get_template).with('my_stack').and_return(@response_stub)
191
+
192
+ @cf.template('my_stack').should == '{EIP: "string"}'
193
+ end
194
+
195
+ it "should trap and re-raise exceptions as SimpleDeploy::Exceptions::CloudFormationError" do
196
+ @cf_mock.should_receive(:get_template).
197
+ with('my_stack').
198
+ and_raise @exception
199
+ SimpleDeploy::AWS::CloudFormation::Error.should_receive(:new).
200
+ with(:exception => @exception).
201
+ and_raise SimpleDeploy::Exceptions::CloudFormationError.new('failed')
202
+
203
+ lambda { @cf.template('my_stack') }.
204
+ should raise_error SimpleDeploy::Exceptions::CloudFormationError
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::AWS::InstanceReader do
4
+ include_context 'double stubbed logger'
5
+ include_context 'double stubbed config', :access_key => 'key',
6
+ :secret_key => 'XXX',
7
+ :region => 'us-west-1'
8
+
9
+ describe "list_stack_instances" do
10
+ before do
11
+ @cloud_formation_mock = mock 'cloud formation'
12
+ @auto_scaling_groups_mock = mock 'auto scaling'
13
+ @ec2_mock = mock 'ec2'
14
+
15
+ instances = ['first',{ 'Instances' => [{ 'InstanceId' => 'i-000001' },
16
+ { 'InstanceId' => 'i-000002' }] }]
17
+ body = { 'DescribeAutoScalingGroupsResult' => { 'AutoScalingGroups' => instances } }
18
+ @list_response = stub 'Fog::Response', :body => body, :any? => true
19
+
20
+ empty_body = { 'DescribeAutoScalingGroupsResult' => { 'AutoScalingGroups' => [] } }
21
+ @empty_response = stub 'Fog::Response', :body => empty_body
22
+
23
+ @describe_response = stub 'Excon::Response', :body => {
24
+ 'reservationSet' => [{
25
+ 'instanceSet' => [{'instanceState' => {'name' => 'running'}},
26
+ {'ipAddress' => '54.10.10.1'},
27
+ {'instanceId' => 'i-123456'},
28
+ {'privateIpAddress' => '192.168.1.1'}]}]
29
+ }
30
+
31
+ SimpleDeploy::AWS::CloudFormation.stub(:new).
32
+ and_return @cloud_formation_mock
33
+ end
34
+
35
+ context "with no ASGs" do
36
+ before do
37
+ @cloud_formation_mock.should_receive(:stack_resources).
38
+ with('stack').
39
+ and_return []
40
+ end
41
+
42
+ it "should return an empty array" do
43
+ instance_reader = SimpleDeploy::AWS::InstanceReader.new
44
+ instance_reader.list_stack_instances('stack').should == []
45
+ end
46
+ end
47
+
48
+ context "with an ASG" do
49
+ before do
50
+ stack_resource_results = [{'StackName' => 'stack',
51
+ 'ResourceType' => 'AWS::AutoScaling::AutoScalingGroup',
52
+ 'PhysicalResourceId' => 'asg1'}]
53
+
54
+ @cloud_formation_mock.should_receive(:stack_resources).
55
+ with('stack').
56
+ and_return stack_resource_results
57
+
58
+ Fog::AWS::AutoScaling.stub(:new).
59
+ and_return @auto_scaling_groups_mock
60
+ end
61
+
62
+ context "with no running instances" do
63
+ it "should return empty array" do
64
+ @auto_scaling_groups_mock.should_receive(:describe_auto_scaling_groups).
65
+ with('AutoScalingGroupNames' => ['asg1']).
66
+ and_return(@empty_response)
67
+
68
+ instance_reader = SimpleDeploy::AWS::InstanceReader.new
69
+ instance_reader.list_stack_instances('stack').should == []
70
+ end
71
+ end
72
+
73
+ context "with running instances" do
74
+ it "should return the reservation set for each running instance" do
75
+ @auto_scaling_groups_mock.should_receive(:describe_auto_scaling_groups).
76
+ with('AutoScalingGroupNames' => ['asg1']).
77
+ and_return(@list_response)
78
+
79
+ Fog::Compute::AWS.stub(:new).
80
+ and_return @ec2_mock
81
+ @ec2_mock.should_receive(:describe_instances).
82
+ with('instance-state-name' => 'running',
83
+ 'instance-id' => ['i-000001', 'i-000002']).
84
+ and_return @describe_response
85
+
86
+ instance_reader = SimpleDeploy::AWS::InstanceReader.new
87
+ instance_reader.list_stack_instances('stack').should == [{
88
+ 'instanceSet' => [{'instanceState' => {'name' => 'running'}},
89
+ {'ipAddress' => '54.10.10.1'},
90
+ {'instanceId' => 'i-123456'},
91
+ {'privateIpAddress' => '192.168.1.1'}]}]
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::AWS::SimpleDB do
4
+ include_context 'double stubbed config', :access_key => 'key',
5
+ :secret_key => 'XXX',
6
+ :region => 'us-west-1'
7
+
8
+ before do
9
+ @response_stub = stub 'Excon::Response', :body => {
10
+ 'RequestId' => 'rid',
11
+ 'Domains' => ['domain1', 'domain2'],
12
+ 'Items' => { 'item1' => { 'key' => ['value'] } },
13
+ 'NextToken' => nil
14
+ }
15
+ @multi_response_stub = stub 'Excon::Response', :body => {
16
+ 'RequestId' => 'rid',
17
+ 'Domains' => ['domain1', 'domain2'],
18
+ 'Items' => { 'item1-2' => { 'key' => ['value'] } },
19
+ 'NextToken' => 'Chunk2'
20
+ }
21
+
22
+ @db_mock = mock 'SimpleDB'
23
+ Fog::AWS::SimpleDB.stub(:new).and_return(@db_mock)
24
+ @db_mock.stub(:list_domains).and_return(@response_stub)
25
+
26
+ @db = SimpleDeploy::AWS::SimpleDB.new
27
+ end
28
+
29
+ describe 'domains' do
30
+ it 'should return a list of domains' do
31
+ @db.domains.should == ['domain1', 'domain2']
32
+ end
33
+ end
34
+
35
+ describe 'domain_exists?' do
36
+ it 'should return true for existing domains' do
37
+ @db.domain_exists?('domain1').should be_true
38
+ end
39
+
40
+ it 'should return false for non-existent domains' do
41
+ @db.domain_exists?('baddomain1').should_not be_true
42
+ end
43
+ end
44
+
45
+ describe 'create_domain' do
46
+ it 'should create a new domain' do
47
+ @db_mock.should_receive(:create_domain).with('newdomain').and_return(@response_stub)
48
+
49
+ @db.create_domain('newdomain').body['RequestId'].should == 'rid'
50
+ end
51
+
52
+ it 'should not create a duplicate domain' do
53
+ @db_mock.should_not_receive(:create_domain)
54
+
55
+ @db.create_domain('domain1').should be_nil
56
+ end
57
+ end
58
+
59
+ describe 'put_attributes' do
60
+ it 'should update the specified domain' do
61
+ @db_mock.should_receive(:put_attributes).with('domain1', 'item1', { 'key' => 'value' }, {}).and_return(@response_stub)
62
+
63
+ @db.put_attributes('domain1', 'item1', { 'key' => 'value' }, {}).body['RequestId'].should == 'rid'
64
+ end
65
+ end
66
+
67
+ describe 'select' do
68
+ it 'should return query items' do
69
+ @db_mock.should_receive(:select).with('item1', { "ConsistentRead" => true, "NextToken" => nil } ).and_return(@response_stub)
70
+
71
+ @db.select('item1').should == { 'item1' => { 'key' => ['value'] } }
72
+ end
73
+
74
+ it 'should return multiple chunks of query items' do
75
+ @db_mock.should_receive(:select).with('item1', { "ConsistentRead" => true, "NextToken" => nil } ).and_return(@multi_response_stub)
76
+ @db_mock.should_receive(:select).with('item1', { "ConsistentRead" => true, "NextToken" => 'Chunk2' } ).and_return(@response_stub)
77
+
78
+ @db.select('item1').should == { 'item1' => { 'key' => ['value'] }, 'item1-2' => { 'key' => ['value'] } }
79
+ end
80
+ end
81
+
82
+ describe 'delete' do
83
+ it 'should delete the attributes identified by domain and key' do
84
+ @db_mock.should_receive(:delete_attributes).with('domain1', 'item1').and_return(@response_stub)
85
+
86
+ @db.delete('domain1', 'item1').body['RequestId'].should == 'rid'
87
+ end
88
+ end
89
+ end