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,6 +1,9 @@
1
1
  require 'spec_helper'
2
+ require 'simple_deploy/cli'
2
3
 
3
4
  describe SimpleDeploy::CLI::Shared do
5
+ include_context 'double stubbed logger'
6
+
4
7
  before do
5
8
  @object = Object.new
6
9
  @object.extend SimpleDeploy::CLI::Shared
@@ -10,9 +13,7 @@ describe SimpleDeploy::CLI::Shared do
10
13
  logger_stub = stub 'logger stub', :info => true
11
14
  attributes = [ 'test1=value1', 'test2=value2==' ]
12
15
 
13
- @object.stub :logger => logger_stub
14
-
15
- @object.parse_attributes(:logger => logger_stub,
16
+ @object.parse_attributes(:logger => @logger_stub,
16
17
  :attributes => attributes).
17
18
  should == [ { "test1" => "value1" },
18
19
  { "test2" => "value2==" } ]
@@ -20,11 +21,8 @@ describe SimpleDeploy::CLI::Shared do
20
21
 
21
22
  context "validating options " do
22
23
  it "should exit if provided options passed do not include all required" do
23
- logger_stub = stub 'logger stub', :error => true
24
-
25
24
  provided = { :test1 => 'test1', :test2 => 'test2' }
26
25
  required = [:test1, :test2, :test3]
27
- @object.stub :logger => logger_stub
28
26
 
29
27
  lambda {
30
28
  @object.valid_options? :provided => provided,
@@ -34,13 +32,12 @@ describe SimpleDeploy::CLI::Shared do
34
32
 
35
33
  it "should exit if environment does not exist" do
36
34
  config_stub = stub 'config stub', :environments => { 'preprod' => 'data' }
37
- logger_stub = stub 'logger stub', :error => true
38
35
 
39
36
  provided = { :environment => 'prod' }
40
37
  required = [:environment]
41
38
 
42
- SimpleDeploy::Config.stub :new => config_stub
43
- @object.stub :logger => logger_stub
39
+ SimpleDeploy.stub(:environments).and_return(config_stub)
40
+ config_stub.should_receive(:keys).and_return(['preprod'])
44
41
 
45
42
  lambda {
46
43
  @object.valid_options? :provided => provided,
@@ -50,16 +47,16 @@ describe SimpleDeploy::CLI::Shared do
50
47
 
51
48
  it "should not exit if all options passed and environment exists" do
52
49
  config_stub = stub 'config stub', :environments => { 'prod' => 'data' }
53
- logger_stub = stub 'logger stub', :error => true
54
50
 
55
51
  provided = { :environment => 'prod', :test1 => 'value1' }
56
52
  required = [:environment, :test1]
57
53
 
58
- SimpleDeploy::Config.stub :new => config_stub
54
+ SimpleDeploy.stub(:environments).and_return(config_stub)
55
+ config_stub.should_receive(:keys).and_return(['prod'])
59
56
 
60
57
  @object.valid_options? :provided => provided,
61
58
  :required => required,
62
- :logger => logger_stub
59
+ :logger => @logger_stub
63
60
  end
64
61
  end
65
62
 
@@ -67,9 +64,9 @@ describe SimpleDeploy::CLI::Shared do
67
64
  @object.command_name.should == 'object'
68
65
  end
69
66
 
70
- it "should rescue stackster exceptions and exit 1" do
71
- lambda { @object.rescue_stackster_exceptions_and_exit do
72
- raise Stackster::Exceptions::Base
67
+ it "should rescue exceptions and exit 1" do
68
+ lambda { @object.rescue_exceptions_and_exit do
69
+ raise SimpleDeploy::Exceptions::Base
73
70
  end
74
71
  }.should raise_error SystemExit
75
72
  end
@@ -3,23 +3,19 @@ require 'spec_helper'
3
3
  require 'simple_deploy/cli'
4
4
 
5
5
  describe SimpleDeploy::CLI::Update do
6
+ include_context 'cli config'
7
+ include_context 'double stubbed logger'
8
+ include_context 'received stack array', 'my_stack', 'my_env', 1
9
+
6
10
  describe 'update' do
7
11
  before do
8
- @config = mock 'config'
9
- @logger = stub 'logger', 'info' => 'true'
10
- @stack = stub :attributes => {}
11
-
12
- SimpleDeploy::Config.stub(:new).and_return(@config)
13
- @config.should_receive(:environment).with('my_env').and_return(@config)
14
- SimpleDeploy::SimpleDeployLogger.should_receive(:new).
15
- with(:log_level => 'debug').
16
- and_return(@logger)
12
+ @stack_mock1.stub(:attributes).and_return({})
17
13
  end
18
14
 
19
15
  it "should pass force true" do
20
16
  options = { :environment => 'my_env',
21
17
  :log_level => 'debug',
22
- :name => ['my_stack'],
18
+ :name => ['my_stack1'],
23
19
  :force => true,
24
20
  :attributes => ['chef_repo_bucket_prefix=intu-lc'] }
25
21
 
@@ -29,14 +25,7 @@ describe SimpleDeploy::CLI::Update do
29
25
 
30
26
  Trollop.stub(:options).and_return(options)
31
27
 
32
- SimpleDeploy::Stack.should_receive(:new).
33
- with(:config => @config,
34
- :environment => 'my_env',
35
- :logger => @logger,
36
- :name => 'my_stack').
37
- and_return(@stack)
38
-
39
- @stack.should_receive(:update).with(hash_including(:force => true))
28
+ @stack_mock1.should_receive(:update).with(hash_including(:force => true))
40
29
 
41
30
  subject.update
42
31
  end
@@ -44,7 +33,7 @@ describe SimpleDeploy::CLI::Update do
44
33
  it "should pass force false" do
45
34
  options = { :environment => 'my_env',
46
35
  :log_level => 'debug',
47
- :name => ['my_stack'],
36
+ :name => ['my_stack1'],
48
37
  :force => false,
49
38
  :attributes => ['chef_repo_bucket_prefix=intu-lc'] }
50
39
 
@@ -54,14 +43,7 @@ describe SimpleDeploy::CLI::Update do
54
43
 
55
44
  Trollop.stub(:options).and_return(options)
56
45
 
57
- SimpleDeploy::Stack.should_receive(:new).
58
- with(:config => @config,
59
- :environment => 'my_env',
60
- :logger => @logger,
61
- :name => 'my_stack').
62
- and_return(@stack)
63
-
64
- @stack.should_receive(:update).with(hash_including(:force => false))
46
+ @stack_mock1.should_receive(:update).with(hash_including(:force => false))
65
47
 
66
48
  subject.update
67
49
  end
data/spec/config_spec.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SimpleDeploy do
3
+ describe SimpleDeploy::Configuration do
4
4
  let(:config_data) do
5
5
  { 'environments' => {
6
6
  'test_env' => {
@@ -14,38 +14,47 @@ describe SimpleDeploy do
14
14
  } } }
15
15
  end
16
16
 
17
- describe 'new' do
17
+ describe 'creating a configuration' do
18
+ before do
19
+ @the_module = SimpleDeploy::Configuration
20
+ end
21
+
18
22
  it 'should accept config data as an argument' do
19
23
  YAML.should_not_receive(:load)
20
24
 
21
- @config = SimpleDeploy::Config.new :config => config_data
22
- @config.config.should == config_data
25
+ @config = @the_module.configure 'test_env', :config => config_data
26
+ @config.environment.should == config_data['environments']['test_env']
27
+ @config.notifications.should == config_data['notifications']
23
28
  end
24
29
 
25
30
  it 'should load the config from ~/.simple_deploy.yml by default' do
26
31
  File.should_receive(:open).with("#{ENV['HOME']}/.simple_deploy.yml").
27
32
  and_return(config_data.to_yaml)
28
- @config = SimpleDeploy::Config.new
29
- @config.config.should == config_data
33
+
34
+ @config = @the_module.configure 'test_env'
35
+ @config.environment.should == config_data['environments']['test_env']
36
+ @config.notifications.should == config_data['notifications']
30
37
  end
31
38
 
32
39
  it 'should load the config from SIMPLE_DEPLOY_CONFIG_FILE if supplied' do
33
40
  File.should_receive(:open).with("/my/config/file").
34
41
  and_return(config_data.to_yaml)
35
42
  env_mock = mock 'env'
36
- SimpleDeploy::Env.stub :new => env_mock
43
+ @the_module.stub(:env).and_return(env_mock)
37
44
  env_mock.should_receive(:load).
38
45
  with('SIMPLE_DEPLOY_CONFIG_FILE').
39
46
  and_return "/my/config/file"
40
- @config = SimpleDeploy::Config.new
41
- @config.config.should == config_data
47
+ @config = @the_module.configure 'test_env'
48
+ @config.environment.should == config_data['environments']['test_env']
49
+ @config.notifications.should == config_data['notifications']
42
50
  end
43
51
 
44
52
  end
45
53
 
46
54
  describe "after creating a configuration" do
47
55
  before do
48
- @config = SimpleDeploy::Config.new :config => config_data
56
+ @the_module = SimpleDeploy::Configuration
57
+ @config = @the_module.configure 'test_env', :config => config_data
49
58
  end
50
59
 
51
60
  it "should return the default artifacts to deploy" do
@@ -61,15 +70,26 @@ describe SimpleDeploy do
61
70
  end
62
71
 
63
72
  it "should return the environment requested" do
64
- @config.environment('test_env').should == ({ 'secret_key' => 'secret', 'access_key' => 'access', 'region' => 'us-west-1' })
73
+ env_config = @config.environment
74
+ env_config['access_key'].should == 'access'
75
+ env_config['secret_key'].should == 'secret'
76
+ env_config['region'].should == 'us-west-1'
65
77
  end
66
78
 
67
79
  it "should return the notifications available" do
68
80
  @config.notifications.should == ( { 'campfire' => { 'token' => 'my_token' } } )
69
81
  end
70
82
 
83
+ it "should return the access_key for the environment" do
84
+ @config.access_key.should == 'access'
85
+ end
86
+
87
+ it "should return the secret_key for the environment" do
88
+ @config.secret_key.should == 'secret'
89
+ end
90
+
71
91
  it "should return the region for the environment" do
72
- @config.region('test_env').should == 'us-west-1'
92
+ @config.region.should == 'us-west-1'
73
93
  end
74
94
 
75
95
  it "should return the deploy script" do
@@ -78,11 +98,24 @@ describe SimpleDeploy do
78
98
 
79
99
  end
80
100
 
101
+ describe 'showing raw configuration for all instances' do
102
+ before do
103
+ @the_module = SimpleDeploy::Configuration
104
+ end
105
+
106
+ it "should return a hash for every environment" do
107
+ environments = @the_module.environments :config => config_data
108
+ environments.keys.should == ['test_env']
109
+ end
110
+ end
111
+
81
112
  describe "gracefully handling yaml file errors" do
82
113
  before do
83
114
  FakeFS.activate!
84
115
  @config_file_path = "#{ENV['HOME']}/.simple_deploy.yml"
85
116
  FileUtils.mkdir_p File.dirname(@config_file_path)
117
+
118
+ @the_module = SimpleDeploy::Configuration
86
119
  end
87
120
 
88
121
  after do
@@ -92,7 +125,7 @@ describe SimpleDeploy do
92
125
 
93
126
  it "should handle a missing file gracefully" do
94
127
  expect {
95
- config = SimpleDeploy::Config.new
128
+ config = @the_module.configure 'test_env'
96
129
  }.to raise_error(RuntimeError, "#{@config_file_path} not found")
97
130
  end
98
131
 
@@ -103,7 +136,7 @@ describe SimpleDeploy do
103
136
  end
104
137
 
105
138
  expect {
106
- config = SimpleDeploy::Config.new
139
+ config = @the_module.configure 'test_env'
107
140
  }.to raise_error(RuntimeError, "#{@config_file_path} is corrupt")
108
141
  end
109
142
  end
@@ -0,0 +1,28 @@
1
+ shared_context "cli config" do
2
+ before do
3
+ @config_mock = mock 'config mock'
4
+ SimpleDeploy.stub(:create_config).and_return(@config_mock)
5
+ SimpleDeploy.stub(:config).and_return(@config_mock)
6
+ end
7
+ end
8
+
9
+ shared_context "received config" do
10
+ before do
11
+ @config_mock = mock 'config mock'
12
+ SimpleDeploy.should_receive(:config).and_return(@config_mock)
13
+ end
14
+ end
15
+
16
+ shared_context "stubbed config" do
17
+ before do
18
+ @config_mock = mock 'config mock'
19
+ SimpleDeploy.stub(:config).and_return(@config_mock)
20
+ end
21
+ end
22
+
23
+ shared_context "double stubbed config" do |methods_hash|
24
+ before do
25
+ @config_stub = stub 'config stub', methods_hash
26
+ SimpleDeploy.stub(:config).and_return(@config_stub)
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+ shared_context "double stubbed logger" do
2
+ before do
3
+ @logger_stub = stub 'logger stub', :debug => true,
4
+ :info => true,
5
+ :warn => true,
6
+ :error => true
7
+ SimpleDeploy.stub(:logger).and_return(@logger_stub)
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ shared_context "stubbed stack" do |name, environment, options|
2
+ before do
3
+ args = { :name => name, :environment => environment }
4
+ args[:use_internal_ips] = options[:internal] if options && options[:internal]
5
+ @stack_mock = mock 'stack mock', args
6
+ SimpleDeploy::Stack.stub(:new).and_return(@stack_mock)
7
+ end
8
+ end
9
+
10
+ shared_context "double stubbed stack" do |name, environment, options|
11
+ before do
12
+ args = { :name => name, :environment => environment }
13
+ args[:use_internal_ips] = options[:internal] if options && options[:internal]
14
+ @stack_stub = stub 'stack stub', args
15
+ SimpleDeploy::Stack.stub(:new).and_return(@stack_stub)
16
+ end
17
+ end
18
+
19
+ shared_context "clone stack pair" do |source_name, source_env, new_name, new_env|
20
+ before do
21
+ @source_stack_stub = stub 'source stack stub', :name => source_name,
22
+ :environment => source_env
23
+ @new_stack_mock = mock 'new stack mock', :name => new_name,
24
+ :environment => new_env
25
+ SimpleDeploy::Stack.stub(:new).and_return(@source_stack_stub, @new_stack_mock)
26
+ end
27
+ end
28
+
29
+ shared_context "received stack array" do |base_name, env, num_instances|
30
+ before do
31
+ 1.upto(num_instances) do |n|
32
+ name = "#{base_name}#{n}"
33
+ stack_mock = mock 'stack mock', :name => name, :environment => env
34
+ self.instance_variable_set(:"@stack_mock#{n}", stack_mock)
35
+ SimpleDeploy::Stack.should_receive(:new).with(:name => name,
36
+ :environment => env).
37
+ and_return(stack_mock)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::EntryLister do
4
+ include_context 'stubbed config'
5
+
6
+ it "should create a list of entries" do
7
+ @simple_db_mock = mock 'simple db'
8
+ SimpleDeploy::AWS::SimpleDB.should_receive(:new).and_return @simple_db_mock
9
+ @simple_db_mock.should_receive(:domain_exists?).
10
+ with("stacks").
11
+ and_return true
12
+ @simple_db_mock.should_receive(:select).
13
+ with("select * from stacks").
14
+ and_return('stack-to-find-us-west-1' => { 'attr1' => 'value1' })
15
+ entry_lister = SimpleDeploy::EntryLister.new
16
+ entry_lister.all.should == ['stack-to-find']
17
+ end
18
+
19
+ it "should return a blank array if the domain does not exist" do
20
+ @simple_db_mock = mock 'simple db'
21
+ SimpleDeploy::AWS::SimpleDB.should_receive(:new).and_return @simple_db_mock
22
+ @simple_db_mock.should_receive(:domain_exists?).
23
+ with("stacks").
24
+ and_return false
25
+ @simple_db_mock.should_receive(:select).
26
+ with("select * from stacks").exactly(0).times
27
+ entry_lister = SimpleDeploy::EntryLister.new
28
+ entry_lister.all.should == []
29
+ end
30
+
31
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleDeploy::Entry do
4
+ include_context 'double stubbed logger'
5
+
6
+ let(:config_data) do
7
+ { 'environments' => {
8
+ 'test_env' => {
9
+ 'secret_key' => 'the-key',
10
+ 'access_key' => 'access',
11
+ 'region' => 'us-west-1'
12
+ } } }
13
+ end
14
+
15
+ before do
16
+ @config = SimpleDeploy.create_config 'test_env', :config => config_data
17
+ end
18
+
19
+ after do
20
+ SimpleDeploy.release_config
21
+ end
22
+
23
+ it "should create a new entry object" do
24
+ @simple_db_mock = mock 'simple db'
25
+ SimpleDeploy::AWS::SimpleDB.should_receive(:new).and_return @simple_db_mock
26
+ @simple_db_mock.should_receive(:create_domain).
27
+ with("stacks").
28
+ and_return true
29
+ entry = SimpleDeploy::Entry.new :name => 'test-stack'
30
+ entry.class.should == SimpleDeploy::Entry
31
+ end
32
+
33
+ it "should find the requested stack in simple db" do
34
+ @simple_db_mock = mock 'simple db'
35
+ SimpleDeploy::AWS::SimpleDB.should_receive(:new).and_return @simple_db_mock
36
+
37
+ @simple_db_mock.should_receive(:create_domain).
38
+ with("stacks").
39
+ and_return true
40
+ SimpleDeploy::Entry.find :name => 'stack-to-find'
41
+ end
42
+
43
+ context "with stack object" do
44
+ before do
45
+ @simple_db_mock = mock 'simple db'
46
+ SimpleDeploy::AWS::SimpleDB.should_receive(:new).and_return @simple_db_mock
47
+ @simple_db_mock.should_receive(:create_domain).
48
+ with("stacks").
49
+ and_return true
50
+ @entry = SimpleDeploy::Entry.new :name => 'test-stack'
51
+ end
52
+
53
+ it "should set the name to region-name for the stack" do
54
+ @entry.name.should == 'test-stack-us-west-1'
55
+ end
56
+
57
+ it "should set the attributes in simple db including default attributes" do
58
+ Timecop.travel Time.utc(2012, 10, 22, 13, 30)
59
+
60
+ @simple_db_mock.should_receive(:select).
61
+ with("select * from stacks where itemName() = 'test-stack-us-west-1'").
62
+ and_return('test-stack-us-west-1' => { 'key1' => ['value1'] })
63
+ @simple_db_mock.should_receive(:put_attributes).
64
+ with("stacks",
65
+ "test-stack-us-west-1",
66
+ { "key" => "value",
67
+ "key1" => "value1",
68
+ "Name" => "test-stack-us-west-1",
69
+ "CreatedAt" => "2012-10-22 13:30:00 UTC" },
70
+ { :replace => ["key1", "key", "Name", "CreatedAt"] } )
71
+ @entry.set_attributes(['key' => 'value'])
72
+
73
+ @entry.save
74
+ end
75
+
76
+ it "should merge custom attributes" do
77
+ @simple_db_mock.should_receive(:select).
78
+ with("select * from stacks where itemName() = 'test-stack-us-west-1'").
79
+ and_return('test-stack' => { 'key1' => ['value1'] })
80
+ @entry.set_attributes(['key1' => 'value2'])
81
+
82
+ @entry.attributes.should == {'key1' => 'value2' }
83
+ end
84
+ end
85
+
86
+ end