require 'lib/executors/stack_executor/stack_servers_persister'

class Devops::Executor::StackExecutor
  RSpec.describe StackServersPersister do
    let(:provider_info) {
      {
        'id' => 'i-new',
        'name' => 'server_name',
        'key_name' => 'key',
        'private_ip' => '127.0.0.1',
        'public_ip' => '127.0.0.2',
        'tags' => {
          'cid:priority' => '3',
          'Name' => 'server1'
        }
      }
    }

    let(:run_list) { ['role[asd]'] }
    let(:provider) { instance_double(Provider::AwsConnector, name: 'ec2') }
    let(:account) { instance_double(Devops::Model::AwsProviderAccount, ssh_key: 'default_key') }
    let(:stack) { build(:stack_aws, environment: 'foo', run_list: run_list) }
    let(:project) { build(:project, id: 'name') }
    let(:env) { build(:environment, id: 'foo') }
    let(:category) { build(:category, id: 'cat') }
    let(:persister) { described_class.new(stack) }

    before do
      allow(project).to receive(:environment) { env }
      allow(env).to receive(:get_category) { category }
      allow(Devops::Model::Project).to receive(:find) { project }
      allow(Devops::Model::Image).to receive(:find) {
        instance_double(Devops::Model::Image, remote_user: 'user')
      }
      allow(stack).to receive(:provider_instance) { provider }
    end

    describe '#persist', clean_db_after_example: true do
      let(:persist) { persister.persist(provider_info) }

      it 'takes id, key_name, private_ip and public_ip attrs from info hash' do
        expect(persist.to_hash).to include(
          'id' => 'i-new',
          'ssh_key' => 'key',
          'private_ip' => '127.0.0.1',
          'public_ip' => '127.0.0.2'
        )
      end

      it 'takes created_by, run_list and stack attrs from stack' do
        expect(persist.to_hash).to include(
          'created_by' => 'root',
          'run_list' => run_list,
          'stack' => 'stack_id'
        )
      end

      # we didn't decide how to set user properly yet
      it 'sets remote_user to ec2-user' do
        expect(persist.remote_user).to eq 'ec2-user'
      end

      it "takes environment from env identifier" do
        expect(persist.environment).to eq 'foo'
      end

      it 'takes category from category id' do
        expect(persist.category).to eq 'cat'
      end

      it "takes default provider's ssh key if info doesn't contain it" do
        allow(stack).to receive(:account_instance) { account }
        provider_info.delete('key_name')
        expect(persist.ssh_key).to eq 'default_key'
      end

      it "sets server's run list to empty array if stack's run_list is nil" do
        stack.run_list = nil
        expect(persist.run_list).to eq []
      end

      it 'build chef_node_name with default mask ":project-:env-:instanceid"' do
        expect(persist.cm_name).to eq 'name-foo-i-new'
        expect(persist.name).to eq 'name-foo-i-new'
      end

      it "builds chef_node_name with custom mask if info['tags']['cid:node-name-mask'] exists" do
        provider_info['tags']['cid:node-name-mask'] = ':project-:instancename-123'
        expect(persist.cm_name).to eq 'name-server1-123'
      end

      it 'sets provider and provider account from stack' do
        stack.provider_account = 'foo'
        expect(persist.provider_account).to eq 'foo'
      end

      describe 'incremented variables' do
        it 'substitutes :increment-groupid: with incrementing numbers' do
          provider_info['tags']['cid:node-name-mask'] = 'node-:increment-group1:-dev'
          expect(persister.persist(provider_info).cm_name).to eq 'node-01-dev'
          provider_info['id'] = 'i-new2'
          expect(persister.persist(provider_info).cm_name).to eq 'node-02-dev'
        end
      end
    end
  end
end