simple_deploy 0.7.2 → 0.7.3

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.
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