require 'db/mongo/models/stack/stack_aws' require 'providers/aws' RSpec.describe Devops::Model::StackAws, type: :model do let(:stack) { build(:stack_aws) } it 'is valid with factory attrs' do expect(build(:stack_aws)).to be_valid end describe 'validation rules:', stubbed_logger: true do include_examples 'field type validation', :id, :not_nil, :non_empty_string include_examples 'field type validation', :project, :not_nil, :non_empty_string include_examples 'field type validation', :environment, :not_nil, :non_empty_string include_examples 'field type validation', :stack_template, :not_nil, :non_empty_string include_examples 'field type validation', :name, :maybe_nil, :non_empty_string include_examples 'field type validation', :owner, :not_nil, :non_empty_string include_examples 'field type validation', :run_list, :maybe_empty_array, :run_list include_examples 'field type validation', :tags, :maybe_nil 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' do it 'returns hash with several fields' do expect(stack.to_hash.keys).to include(*%w(provider project environment stack_template name owner run_list tags)) end end describe '#initialize' do it 'sets provider to aws even if given attrs don\'t contain it' do expect(described_class.new.provider).to eq 'aws' end it 'sets tags to empty hash if it\'s blank' do begin expect(create(:stack_aws).tags).to eq({}) ensure Devops::Model::StackAws.delete_all end 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 '#sync_status_and_events!' do let(:fresh_events) { double('fresh_events') } let(:provider) { instance_double(Provider::AwsConnector, 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_status_and_events!}.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_status_and_events!}.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, TemplateURL and Capabilities' do permitted_keys = %w(Parameters 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(:update_in_cloud!) end it 'updates stack_template' do allow(stack).to receive(:stack_template_model) { build(:stack_template_aws) } expect(stack).to receive(:save) 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_status_and_events!) 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_status_and_events!) subject end end describe 'lock_persisting!', clean_db_after_example: true do it 'sets #persisting_is_locked to true' do stack = create(:stack, persisting_is_locked: false) expect(stack.persisting_is_locked).to be false stack.lock_persisting! expect(stack.persisting_is_locked).to be true expect(stack.reload.persisting_is_locked).to be true end end describe 'unlock_persisting!', clean_db_after_example: true do it 'sets #persisting_is_locked to false' do stack = create(:stack, persisting_is_locked: true) expect(stack.persisting_is_locked).to be true stack.unlock_persisting! expect(stack.persisting_is_locked).to be false expect(stack.reload.persisting_is_locked).to be false end end end