require 'db/mongo/models/stack/stack_ec2' RSpec.describe Devops::Model::StackEc2, type: :model do let(:stack) { build(:stack_ec2) } before do allow(Provider::ProviderFactory).to receive(:providers).and_return(%w(ec2)) end it 'is valid with factory attrs' do expect(build(:stack_ec2)).to be_valid end describe 'validation rules:', stubbed_logger: true do include_examples 'field type validation', :id, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :project, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :deploy_env, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :stack_template, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :name, :maybe_nil, :non_empty_string, :field_validator include_examples 'field type validation', :owner, :not_nil, :non_empty_string, :field_validator include_examples 'field type validation', :run_list, :maybe_nil, :maybe_empty_array, :run_list, :field_validator it 'validates provider' do stack.provider = nil expect(stack).not_to be_valid stack.provider = '' expect(stack).not_to be_valid end end describe '#to_hash_without_id' do it 'returns hash with several fields' do expect(stack.to_hash_without_id.keys).to include('provider', :project, :deploy_env, :stack_template, :name, :owner, :run_list) end end describe '#initialize' do it 'sets provider to ec2 even if given attrs don\'t contain it' do expect(described_class.new.provider).to eq 'ec2' end it 'sets run_list to empty array if it\'s blank' do expect(described_class.new.run_list).to eq [] end end describe '#create_stack_in_cloud!' do it 'calls create_stack method of provider instance' do expect(stack).to receive_message_chain('provider_instance.create_stack') stack.create_stack_in_cloud!('') end it 'raises InvalidRecord if stack with such name already exists in cloud' do allow(stack).to receive_message_chain('provider_instance.create_stack').and_raise(ProviderErrors::NameConflict) expect { stack.create_stack_in_cloud!('') }.to raise_error(InvalidRecord) end end describe '#delete_stack_in_cloud!' do it 'calls delete_stack method of provider instance' do expect(stack).to receive_message_chain('provider_instance.delete_stack').with(stack) stack.delete_stack_in_cloud! end end describe '#template_body' do it 'is a String' do allow(Devops::Db).to receive_message_chain('connector.stack_template.template_body') {'body'} expect(stack.template_body).to be_a(String) end end describe '#sync!' do let(:fresh_events) { double('fresh_events') } let(:provider) { instance_double('Provider::Ec2', stack_details: {stack_status: 'CREATE_COMPLETE'}, stack_events: fresh_events ) } before do allow(stack).to receive(:provider_instance) {provider} end it "get fresh stack details and updates stack status" do expect(provider).to receive(:stack_details) expect {stack.sync!}.to change {stack.stack_status}.from(nil).to('CREATE_COMPLETE') end it "get fresh stack events and stores it in @events" do expect(stack).to receive_message_chain('provider_instance.stack_events') expect {stack.sync!}.to change {stack.events}.from(nil).to(fresh_events) end end describe '#update_in_cloud!' do before { allow(stack).to receive_message_chain('provider_instance.update_stack') } it 'calls to method update_stack of provider instance' do expect(stack).to receive_message_chain('provider_instance.update_stack') stack.update_in_cloud!({}) end it 'filters params to include only Parameters, TemplateBody, TemplateURL and Capabilities' do permitted_keys = %w(Parameters TemplateBody TemplateURL Capabilities) permitted_hash = permitted_keys.inject({}) {|hash, key| hash[key] = 1; hash} unfiltered_hash = permitted_hash.merge('wrong' => 1) expect(stack).to receive_message_chain('provider_instance.update_stack').with(stack, permitted_hash) stack.update_in_cloud!(unfiltered_hash) end end describe '#change_stack_template!' do let(:new_template) { 'brand_new_template' } before do allow(stack).to receive(:template_body) allow(stack).to receive(:update_in_cloud!) allow(Devops::Db).to receive_message_chain('connector.stack_update') end it 'updates stack_template' do stack.change_stack_template!(new_template) expect(stack.stack_template).to eq new_template end end describe '.create' do subject { described_class.create({}, '') } before do allow_any_instance_of(described_class).to receive(:create_stack_in_cloud!) allow_any_instance_of(described_class).to receive(:sync!) end it "returns instance of #{described_class.name}" do expect(subject).to be_a(described_class) end it 'creates stack in AWS' do expect_any_instance_of(described_class).to receive(:create_stack_in_cloud!) subject end it 'synchronizes details' do expect_any_instance_of(described_class).to receive(:sync!) subject end end describe '.build_from_bson' do subject { described_class.build_from_bson('_id' => 'foo', 'name' => 'bar') } it "returns instance of #{described_class.name} with given parameters" do expect(subject.id).to eq 'foo' expect(subject.name).to eq 'bar' end end end