automan 2.3.6 → 2.3.7

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +5 -0
  5. data/Rakefile +5 -0
  6. data/automan.gemspec +3 -3
  7. data/lib/automan/base.rb +7 -3
  8. data/lib/automan/beanstalk/deployer.rb +1 -1
  9. data/lib/automan/beanstalk/package.rb +1 -1
  10. data/lib/automan/beanstalk/router.rb +1 -1
  11. data/lib/automan/cli/snapper.rb +29 -29
  12. data/lib/automan/cli/stacker.rb +19 -0
  13. data/lib/automan/cloudformation/launcher.rb +6 -3
  14. data/lib/automan/cloudformation/replacer.rb +1 -1
  15. data/lib/automan/cloudformation/terminator.rb +1 -1
  16. data/lib/automan/ec2/image.rb +3 -3
  17. data/lib/automan/elasticache/router.rb +79 -0
  18. data/lib/automan/mixins/aws_caller.rb +21 -7
  19. data/lib/automan/rds/snapshot.rb +35 -14
  20. data/lib/automan/s3/downloader.rb +10 -1
  21. data/lib/automan/version.rb +1 -1
  22. data/lib/automan.rb +1 -0
  23. data/spec/beanstalk/application_spec.rb +17 -17
  24. data/spec/beanstalk/configuration_spec.rb +24 -24
  25. data/spec/beanstalk/deployer_spec.rb +65 -65
  26. data/spec/beanstalk/router_spec.rb +18 -19
  27. data/spec/beanstalk/terminator_spec.rb +16 -16
  28. data/spec/beanstalk/uploader_spec.rb +13 -13
  29. data/spec/beanstalk/version_spec.rb +8 -10
  30. data/spec/cloudformation/launcher_spec.rb +63 -65
  31. data/spec/cloudformation/replacer_spec.rb +10 -10
  32. data/spec/cloudformation/terminator_spec.rb +23 -23
  33. data/spec/cloudformation/uploader_spec.rb +13 -13
  34. data/spec/ec2/image_spec.rb +55 -55
  35. data/spec/ec2/instance_spec.rb +17 -17
  36. data/spec/elasticache/router_spec.rb +29 -0
  37. data/spec/mixins/aws_caller_spec.rb +9 -9
  38. data/spec/mixins/utils_spec.rb +27 -28
  39. data/spec/rds/snapshot_spec.rb +44 -46
  40. data/templates/stacker/.env.example +14 -0
  41. data/templates/stacker/.gitignore +2 -0
  42. data/templates/stacker/.ruby-gemset.tt +1 -0
  43. data/templates/stacker/.ruby-version +1 -0
  44. data/templates/stacker/Gemfile +4 -0
  45. data/templates/stacker/bin/%app_name%.tt +62 -0
  46. data/templates/stacker/bin/launch_%app_name%.sh.tt +12 -0
  47. metadata +20 -7
@@ -17,30 +17,29 @@ describe Automan::Cloudformation::Launcher do
17
17
  it { should respond_to :stack_update_complete? }
18
18
 
19
19
  describe '#read_manifest' do
20
- subject(:s) do
20
+ subject() do
21
21
  AWS.stub!
22
- s = Automan::Cloudformation::Launcher.new
23
- s
22
+ Automan::Cloudformation::Launcher.new
24
23
  end
25
24
 
26
25
  it 'raises MissingManifestError if manifest does not exist' do
27
- s.stub(:manifest_exists?).and_return(false)
26
+ allow(subject).to receive(:manifest_exists?).and_return(false)
28
27
  expect {
29
- s.read_manifest
28
+ subject.read_manifest
30
29
  }.to raise_error(Automan::Cloudformation::MissingManifestError)
31
30
  end
32
31
 
33
32
  it 'merges manifest contents into parameters hash' do
34
- s.stub(:manifest_exists?).and_return(true)
35
- s.stub(:s3_read).and_return('{"foo": "bar", "big": "poppa"}')
36
- s.parameters = {'foo'=> 'baz', 'fo'=> 'shizzle'}
37
- s.read_manifest
38
- s.parameters.should eq({'foo' => 'bar', 'fo' => 'shizzle', 'big' => 'poppa'})
33
+ allow(subject).to receive(:manifest_exists?).and_return(true)
34
+ allow(subject).to receive(:s3_read).and_return('{"foo": "bar", "big": "poppa"}')
35
+ subject.parameters = {'foo'=> 'baz', 'fo'=> 'shizzle'}
36
+ subject.read_manifest
37
+ expect(subject.parameters).to eq({'foo' => 'bar', 'fo' => 'shizzle', 'big' => 'poppa'})
39
38
  end
40
39
  end
41
40
 
42
41
  describe '#parse_template_parameters' do
43
- subject(:s) do
42
+ subject() do
44
43
  AWS.stub!
45
44
  s = Automan::Cloudformation::Launcher.new
46
45
  s.cfn = AWS::CloudFormation.new
@@ -49,31 +48,30 @@ describe Automan::Cloudformation::Launcher do
49
48
  end
50
49
 
51
50
  it "returns a hash" do
52
- s.template = File.join(File.dirname(__FILE__), 'templates', 'worker_role.json')
53
- result = s.parse_template_parameters
54
- result.class.should eq(Hash)
51
+ subject.template = File.join(File.dirname(__FILE__), 'templates', 'worker_role.json')
52
+ result = subject.parse_template_parameters
53
+ expect(result.class).to eq(Hash)
55
54
  end
56
55
 
57
56
  end
58
57
 
59
58
  describe '#template_handle' do
60
- subject(:s) do
59
+ subject() do
61
60
  AWS.stub!
62
- s = Automan::Cloudformation::Launcher.new
63
- s
61
+ Automan::Cloudformation::Launcher.new
64
62
  end
65
63
 
66
64
  it "returns an s3 key if it is an s3 path" do
67
- s.template_handle("s3://foo/bar/baz").should be_a AWS::S3::S3Object
65
+ expect(subject.template_handle("s3://foo/bar/baz")).to be_a AWS::S3::S3Object
68
66
  end
69
67
 
70
68
  it "returns a string if it is a local file" do
71
- s.template_handle(__FILE__).should be_a String
69
+ expect(subject.template_handle(__FILE__)).to be_a String
72
70
  end
73
71
  end
74
72
 
75
73
  describe '#validate_parameters' do
76
- subject(:s) do
74
+ subject() do
77
75
  AWS.stub!
78
76
  s = Automan::Cloudformation::Launcher.new
79
77
  s.logger = Logger.new('/dev/null')
@@ -82,99 +80,99 @@ describe Automan::Cloudformation::Launcher do
82
80
  end
83
81
 
84
82
  it "raises error if no parameters were specified" do
85
- s.parameters = nil
83
+ subject.parameters = nil
86
84
  expect {
87
- s.validate_parameters
85
+ subject.validate_parameters
88
86
  }.to raise_error Automan::Cloudformation::MissingParametersError
89
87
  end
90
88
 
91
89
  it "raises error if the template doesn't validate" do
92
- Automan::Cloudformation::Launcher.any_instance.stub(:parse_template_parameters).and_return({code: 'foo', message: 'bar'})
90
+ allow(subject).to receive(:parse_template_parameters).and_return({code: 'foo', message: 'bar'})
93
91
  expect {
94
- s.validate_parameters
92
+ subject.validate_parameters
95
93
  }.to raise_error Automan::Cloudformation::BadTemplateError
96
94
  end
97
95
 
98
96
  it "raises error if a required parameter isn't present" do
99
- Automan::Cloudformation::Launcher.any_instance.stub(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo'}])
97
+ allow(subject).to receive(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo'}])
100
98
  expect {
101
- s.validate_parameters
99
+ subject.validate_parameters
102
100
  }.to raise_error Automan::Cloudformation::MissingParametersError
103
101
  end
104
102
 
105
103
  it "raises no error if all required parameters are present" do
106
- Automan::Cloudformation::Launcher.any_instance.stub(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo'}])
107
- s.parameters = {'foo' => 'bar'}
104
+ allow(subject).to receive(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo'}])
105
+ subject.parameters = {'foo' => 'bar'}
108
106
  expect {
109
- s.validate_parameters
107
+ subject.validate_parameters
110
108
  }.not_to raise_error
111
109
  end
112
110
 
113
111
  it "raises no error if there are no required parameters" do
114
- Automan::Cloudformation::Launcher.any_instance.stub(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo', default_value: 'bar'}])
112
+ allow(subject).to receive(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo', default_value: 'bar'}])
115
113
  expect {
116
- s.validate_parameters
114
+ subject.validate_parameters
117
115
  }.not_to raise_error
118
116
  end
119
117
  end
120
118
 
121
119
  describe '#update' do
122
- subject(:s) do
120
+ subject() do
123
121
  AWS.stub!
124
122
  s = Automan::Cloudformation::Launcher.new
125
123
  s.logger = Logger.new('/dev/null')
126
- s.stub(:template_handle).and_return('foo')
124
+ allow(s).to receive(:template_handle).and_return('foo')
127
125
  s
128
126
  end
129
127
 
130
128
  it "ignores AWS::CloudFormation::Errors::ValidationError when no updates are to be performed" do
131
- s.stub(:update_stack).and_raise AWS::CloudFormation::Errors::ValidationError.new("No updates are to be performed.")
129
+ allow(subject).to receive(:update_stack).and_raise AWS::CloudFormation::Errors::ValidationError.new("No updates are to be performed.")
132
130
  expect {
133
- s.update
131
+ subject.update
134
132
  }.to_not raise_error
135
133
  end
136
134
 
137
135
  it 're-raises any other ValidationError' do
138
- s.stub(:update_stack).and_raise AWS::CloudFormation::Errors::ValidationError.new("foo")
136
+ allow(subject).to receive(:update_stack).and_raise AWS::CloudFormation::Errors::ValidationError.new("foo")
139
137
  expect {
140
- s.update
138
+ subject.update
141
139
  }.to raise_error AWS::CloudFormation::Errors::ValidationError
142
140
  end
143
141
  end
144
142
 
145
143
  describe '#launch_or_update' do
146
- subject(:s) do
144
+ subject() do
147
145
  AWS.stub!
148
146
  s = Automan::Cloudformation::Launcher.new
149
147
  s.logger = Logger.new('/dev/null')
150
- s.stub(:validate_parameters)
148
+ allow(s).to receive(:validate_parameters)
151
149
  s
152
150
  end
153
151
 
154
152
  it "launches a new stack if it does not exist" do
155
- s.stub(:stack_exists?).and_return(false)
156
- s.should_receive(:launch)
157
- s.launch_or_update
153
+ allow(subject).to receive(:stack_exists?).and_return(false)
154
+ expect(subject).to receive(:launch)
155
+ subject.launch_or_update
158
156
  end
159
157
 
160
158
  it "updates an existing stack if update is enabled" do
161
- s.stub(:stack_exists?).and_return(true)
162
- s.stub(:enable_update).and_return(true)
163
- s.should_receive(:update)
164
- s.launch_or_update
159
+ allow(subject).to receive(:stack_exists?).and_return(true)
160
+ allow(subject).to receive(:enable_update).and_return(true)
161
+ expect(subject).to receive(:update)
162
+ subject.launch_or_update
165
163
  end
166
164
 
167
165
  it "raises an error when updating an existing stack w/o update enabled" do
168
- s.stub(:stack_exists?).and_return(true)
169
- s.stub(:enable_update).and_return(false)
166
+ allow(subject).to receive(:stack_exists?).and_return(true)
167
+ allow(subject).to receive(:enable_update).and_return(false)
170
168
  expect {
171
- s.launch_or_update
169
+ subject.launch_or_update
172
170
  }.to raise_error Automan::Cloudformation::StackExistsError
173
171
  end
174
172
  end
175
173
 
176
174
  describe '#stack_launch_complete?' do
177
- subject(:s) do
175
+ subject() do
178
176
  AWS.stub!
179
177
  s = Automan::Cloudformation::Launcher.new
180
178
  s.logger = Logger.new('/dev/null')
@@ -182,35 +180,35 @@ describe Automan::Cloudformation::Launcher do
182
180
  end
183
181
 
184
182
  it 'returns true when the stack completes' do
185
- s.stub(:stack_status).and_return('CREATE_COMPLETE')
186
- s.stack_launch_complete?.should be_true
183
+ allow(subject).to receive(:stack_status).and_return('CREATE_COMPLETE')
184
+ expect(subject.stack_launch_complete?).to be_truthy
187
185
  end
188
186
 
189
187
  it 'raises an error when the stack fails' do
190
- s.stub(:stack_status).and_return('CREATE_FAILED')
188
+ allow(subject).to receive(:stack_status).and_return('CREATE_FAILED')
191
189
  expect {
192
- s.stack_launch_complete?
190
+ subject.stack_launch_complete?
193
191
  }.to raise_error Automan::Cloudformation::StackCreationError
194
192
  end
195
193
 
196
194
  rollback_states = %w[ROLLBACK_COMPLETE ROLLBACK_FAILED ROLLBACK_IN_PROGRESS]
197
195
  rollback_states.each do |state|
198
196
  it "raises an error when the stack goes into #{state} state" do
199
- s.stub(:stack_status).and_return(state)
197
+ allow(subject).to receive(:stack_status).and_return(state)
200
198
  expect {
201
- s.stack_launch_complete?
199
+ subject.stack_launch_complete?
202
200
  }.to raise_error Automan::Cloudformation::StackCreationError
203
201
  end
204
202
  end
205
203
 
206
204
  it 'returns false for any other state' do
207
- s.stub(:stack_status).and_return('foo')
208
- s.stack_launch_complete?.should be_false
205
+ allow(subject).to receive(:stack_status).and_return('foo')
206
+ expect(subject.stack_launch_complete?).to be_falsey
209
207
  end
210
208
  end
211
209
 
212
210
  describe '#stack_update_complete?' do
213
- subject(:s) do
211
+ subject() do
214
212
  AWS.stub!
215
213
  s = Automan::Cloudformation::Launcher.new
216
214
  s.logger = Logger.new('/dev/null')
@@ -218,23 +216,23 @@ describe Automan::Cloudformation::Launcher do
218
216
  end
219
217
 
220
218
  it 'returns true when the stack completes' do
221
- s.stub(:stack_status).and_return('UPDATE_COMPLETE')
222
- s.stack_update_complete?.should be_true
219
+ allow(subject).to receive(:stack_status).and_return('UPDATE_COMPLETE')
220
+ expect(subject.stack_update_complete?).to be_truthy
223
221
  end
224
222
 
225
223
  rollback_states = %w[UPDATE_ROLLBACK_COMPLETE UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_IN_PROGRESS]
226
224
  rollback_states.each do |state|
227
225
  it "raises an error when the stack enters #{state} state" do
228
- s.stub(:stack_status).and_return(state)
226
+ allow(subject).to receive(:stack_status).and_return(state)
229
227
  expect {
230
- s.stack_update_complete?
228
+ subject.stack_update_complete?
231
229
  }.to raise_error Automan::Cloudformation::StackUpdateError
232
230
  end
233
231
  end
234
232
 
235
233
  it 'returns false for any other state' do
236
- s.stub(:stack_status).and_return('foo')
237
- s.stack_update_complete?.should be_false
234
+ allow(subject).to receive(:stack_status).and_return('foo')
235
+ expect(subject.stack_update_complete?).to be_falsey
238
236
  end
239
237
  end
240
238
  end
@@ -1,15 +1,15 @@
1
1
  require 'automan'
2
2
 
3
3
  describe Automan::Cloudformation::Replacer do
4
- it { should respond_to :name }
5
- it { should respond_to :replace_instances }
6
- it { should respond_to :ok_to_replace_instances? }
7
- it { should respond_to :stack_exists? }
4
+ it { is_expected.to respond_to :name }
5
+ it { is_expected.to respond_to :replace_instances }
6
+ it { is_expected.to respond_to :ok_to_replace_instances? }
7
+ it { is_expected.to respond_to :stack_exists? }
8
8
 
9
9
  describe '#ok_to_replace_instances?' do
10
- subject(:r) do
10
+ subject() do
11
11
  AWS.stub!
12
- r = Automan::Cloudformation::Replacer.new
12
+ Automan::Cloudformation::Replacer.new
13
13
  end
14
14
 
15
15
  good_states = %w[UPDATE_COMPLETE]
@@ -30,28 +30,28 @@ describe Automan::Cloudformation::Replacer do
30
30
 
31
31
  good_states.each do |state|
32
32
  it "returns true when stack is in the right state (state: #{state})" do
33
- r.ok_to_replace_instances?(state, Time.now).should be_true
33
+ expect(subject.ok_to_replace_instances?(state, Time.now)).to be_truthy
34
34
  end
35
35
  end
36
36
 
37
37
  good_states.each do |state|
38
38
  it "returns false when stack is in the right state but has not been updated in the last 5m" do
39
39
  last_updated = Time.now - (5 * 60 + 1)
40
- r.ok_to_replace_instances?(state, last_updated).should be_false
40
+ expect(subject.ok_to_replace_instances?(state, last_updated)).to be_falsey
41
41
  end
42
42
  end
43
43
 
44
44
  bad_states.each do |state|
45
45
  it "raises error when stack is borked (state: #{state})" do
46
46
  expect {
47
- r.ok_to_replace_instances?(state, Time.now)
47
+ subject.ok_to_replace_instances?(state, Time.now)
48
48
  }.to raise_error Automan::Cloudformation::StackBrokenError
49
49
  end
50
50
  end
51
51
 
52
52
  wait_states.each do |state|
53
53
  it "returns false when it is not yet ok to replace (state: #{state})" do
54
- r.ok_to_replace_instances?(state, Time.now).should be_false
54
+ expect(subject.ok_to_replace_instances?(state, Time.now)).to be_falsey
55
55
  end
56
56
  end
57
57
  end
@@ -1,15 +1,15 @@
1
1
  require 'automan'
2
2
 
3
3
  describe Automan::Cloudformation::Terminator do
4
- it { should respond_to :name }
5
- it { should respond_to :terminate }
6
- it { should respond_to :stack_exists? }
7
- it { should respond_to :stack_deleted? }
8
- it { should respond_to :delete_stack }
9
- it { should respond_to :wait_for_completion }
4
+ it { is_expected.to respond_to :name }
5
+ it { is_expected.to respond_to :terminate }
6
+ it { is_expected.to respond_to :stack_exists? }
7
+ it { is_expected.to respond_to :stack_deleted? }
8
+ it { is_expected.to respond_to :delete_stack }
9
+ it { is_expected.to respond_to :wait_for_completion }
10
10
 
11
11
  describe '#terminate' do
12
- subject(:t) do
12
+ subject() do
13
13
  AWS.stub!
14
14
  t = Automan::Cloudformation::Terminator.new
15
15
  t.logger = Logger.new('/dev/null')
@@ -17,20 +17,20 @@ describe Automan::Cloudformation::Terminator do
17
17
  end
18
18
 
19
19
  it 'should call #delete_stack if the stack exists' do
20
- t.stub(:stack_exists?).and_return(true)
21
- t.should_receive :delete_stack
22
- t.terminate
20
+ allow(subject).to receive(:stack_exists?).and_return(true)
21
+ expect(subject).to receive :delete_stack
22
+ subject.terminate
23
23
  end
24
24
 
25
25
  it 'should not call #delete_stack if the stack does not exist' do
26
- t.stub(:stack_exists?).and_return(false)
27
- t.should_not_receive :delete_stack
28
- t.terminate
26
+ allow(subject).to receive(:stack_exists?).and_return(false)
27
+ expect(subject).to_not receive :delete_stack
28
+ subject.terminate
29
29
  end
30
30
  end
31
31
 
32
32
  describe '#stack_deleted?' do
33
- subject(:t) do
33
+ subject() do
34
34
  AWS.stub!
35
35
  t = Automan::Cloudformation::Terminator.new
36
36
  t.logger = Logger.new('/dev/null')
@@ -38,26 +38,26 @@ describe Automan::Cloudformation::Terminator do
38
38
  end
39
39
 
40
40
  it 'returns true if the stack does not exist' do
41
- t.stub(:stack_exists?).and_return(false)
42
- t.stub(:stack_status).and_raise StandardError
43
- t.stack_deleted?('foo').should be_true
41
+ allow(subject).to receive(:stack_exists?).and_return(false)
42
+ allow(subject).to receive(:stack_status).and_raise StandardError
43
+ expect(subject.stack_deleted?('foo')).to be_truthy
44
44
  end
45
45
 
46
46
  it 'returns true when status is DELETE_COMPLETE' do
47
- t.stub(:stack_status).and_return('DELETE_COMPLETE')
48
- t.stack_deleted?('foo').should be_true
47
+ allow(subject).to receive(:stack_status).and_return('DELETE_COMPLETE')
48
+ expect(subject.stack_deleted?('foo')).to be_truthy
49
49
  end
50
50
 
51
51
  it 'raises an error when the delete fails' do
52
- t.stub(:stack_status).and_return('DELETE_FAILED')
52
+ allow(subject).to receive(:stack_status).and_return('DELETE_FAILED')
53
53
  expect {
54
- t.stack_deleted?('foo')
54
+ subject.stack_deleted?('foo')
55
55
  }.to raise_error Automan::Cloudformation::StackDeletionError
56
56
  end
57
57
 
58
58
  it 'returns false for any other status' do
59
- t.stub(:stack_status).and_return('foo')
60
- t.stack_deleted?('foo').should be_false
59
+ allow(subject).to receive(:stack_status).and_return('foo')
60
+ expect(subject.stack_deleted?('foo')).to be_falsey
61
61
  end
62
62
  end
63
63
  end
@@ -1,11 +1,11 @@
1
1
  require 'automan'
2
2
 
3
3
  describe Automan::Cloudformation::Uploader do
4
- subject(:u) do
4
+ subject() do
5
5
  AWS.stub!
6
6
  u = Automan::Cloudformation::Uploader.new
7
7
  u.logger = Logger.new('/dev/null')
8
- u.stub(:templates).and_return(%w[a b c])
8
+ allow(u).to receive(:templates).and_return(%w[a b c])
9
9
  u
10
10
  end
11
11
 
@@ -16,35 +16,35 @@ describe Automan::Cloudformation::Uploader do
16
16
 
17
17
  describe '#all_templates_valid?' do
18
18
  it "raises error if there are no templates" do
19
- u.stub(:templates).and_return([])
19
+ allow(subject).to receive(:templates).and_return([])
20
20
  expect {
21
- u.all_templates_valid?
21
+ subject.all_templates_valid?
22
22
  }.to raise_error Automan::Cloudformation::NoTemplatesError
23
23
  end
24
24
 
25
25
  it 'returns true if templates are valid' do
26
- u.should_receive(:template_valid?).exactly(3).times.and_return(true)
27
- u.all_templates_valid?.should be_true
26
+ expect(subject).to receive(:template_valid?).exactly(3).times.and_return(true)
27
+ expect(subject.all_templates_valid?).to be_truthy
28
28
  end
29
29
 
30
30
  it 'returns false if any templates are invalid' do
31
- u.stub(:template_valid?).and_return(false)
32
- u.all_templates_valid?.should be_false
31
+ allow(subject).to receive(:template_valid?).and_return(false)
32
+ expect(subject.all_templates_valid?).to be_falsey
33
33
  end
34
34
  end
35
35
 
36
36
  describe '#upload_templates' do
37
37
  it 'raises error if any template fails validation' do
38
- u.stub(:all_templates_valid?).and_return(false)
38
+ allow(subject).to receive(:all_templates_valid?).and_return(false)
39
39
  expect {
40
- u.upload_templates
40
+ subject.upload_templates
41
41
  }.to raise_error(Automan::Cloudformation::InvalidTemplateError)
42
42
  end
43
43
 
44
44
  it 'uploads files if all are valid' do
45
- u.stub(:all_templates_valid?).and_return(true)
46
- u.should_receive(:upload_file).exactly(3).times
47
- u.upload_templates
45
+ allow(subject).to receive(:all_templates_valid?).and_return(true)
46
+ expect(subject).to receive(:upload_file).exactly(3).times
47
+ subject.upload_templates
48
48
  end
49
49
  end
50
50
  end