require_relative "../support/spec_helper"

module Dalmatian
  RSpec.describe AuroraTest do
    let(:helper) { class_double(Helper, change_to: true, run!: true, git_checkout: true) }
    let(:logger) { class_double(Logger, info: true) }

    let(:terraform) do
      class_double(
        Terraform,
        fmt: true,
        init: true,
        validate: true,
        ensure_presence_of_workspace: true
      )
    end

    let(:aurora) do
      instance_double(
        Aurora,
        identifier: "testaurora",
        in_use_by: [
          "test-service"
        ],
        clusters_in_use: {
          "production" => [
            "test"
          ],
          "staging" => [
            "test"
          ]
        },
        minimum_size: {
          "production" => 2,
          "staging" => 1
        },
        maximum_size: {
          "production" => 2,
          "staging" => 1
        },
        engine: "aurora-postgresql",
        engine_version: "11.9",
        db_name: "testapp",
        port: 5432,
        maintenance_window: "mon:19:00-mon:19:30",
        backup_window: "09:00-10:00",
        backup_retention_period: 31,
        force_ssl: true,
        cluster_id: "new-dedicated-cluster-id",
        account_id: 123456789012,
        parameter_store_path_db_url_name: "DATABASE_URL",
        sql_backup_scheduled_task_environment_variables: [
          {
            "name" => "foo",
            "value" => "bar"
          }
        ],
        check_sql_backup_scheduled_task_environment_variables: [
          {
            "name" => "foo",
            "value" => "bar"
          }
        ],
        sync_sql_backup_to_azure: false,
        replication_bucket_destination_arn: "arn:aws:s3:::dest-bucket",
        replication_kms_key_id: "key-id",
        to_params: {
          "identifier" => "testaurora",
          "in_use_by" => ["test-service"],
          "clusters_in_use" => {"production" => ["test"], "staging" => ["test"]},
          "minimum_size" => {"production" => 2, "staging" => 1},
          "maximum_size" => {"production" => 2, "staging" => 1},
          "engine" => "aurora-postgresql",
          "engine_version" => "11.9",
          "db_name" => "testapp",
          "port" => 5432,
          "force_ssl" => true,
          "maintenance_window" => "mon:19:00-mon:19:30",
          "backup_window" => "09:00-10:00",
          "backup_retention_period" => 31,
          "parameter_store_path_db_url_name" => "DATABASE_URL",
          "sql_backup_scheduled_task_environment_variables" => [
            {
              "name" => "foo",
              "value" => "bar"
            }
          ],
          "check_sql_backup_scheduled_task_environment_variables" => [
            {
              "name" => "foo",
              "value" => "bar"
            }
          ],
          "sync_sql_backup_to_azure" => false,
          "replication_bucket_destination_arn" => "arn:aws:s3:::dest-bucket",
          "replication_kms_key_id" => "key-id"
        }
      )
    end

    let!(:aurora_test) do
      AuroraTest.new(
        aurora: aurora,
        env: {name: "staging", details: {"min_servers" => 2, "max_servers" => 4}},
        helper: helper,
        logger: logger,
        terraform: terraform
      )
    end

    describe "#call" do
      before do
        allow(Terraform).to receive(:init)
        allow(Terraform).to receive(:ensure_presence_of_workspace)
        allow(logger).to receive(:info)
      end

      let(:workspace_name) { "new-dedicated-cluster-id-testaurora-aurora-staging" }

      before { aurora_test.call }

      it "changes to the aurora infrastructure directory" do
        directory = File.join(
          Infrastructure::APP_ROOT,
          Infrastructure::PATH,
          "aurora"
        )

        expect(helper).to have_received(:change_to).with(directory)
      end

      it "logs our intention to run Terraform init" do
        expect(logger).to have_received(:info).with(
          "Running terraform init for #{workspace_name}"
        )
      end

      it "runs Terraform init, with upgrade option" do
        expect(terraform).to have_received(:init).with(upgrade: true)
      end

      it "ensures presence of workspace" do
        expect(terraform).to have_received(:ensure_presence_of_workspace)
          .with(workspace_name)
      end

      it "logs our intention to run Terraform fmt" do
        expect(logger).to have_received(:info).with(
          "Running terraform fmt for #{workspace_name}"
        )
      end

      it "runs Terraform fmt with check and diff options" do
        expect(terraform).to have_received(:fmt).with("-check -diff")
      end

      it "logs our intention to run Terraform validate" do
        expect(logger).to have_received(:info).with(
          "Running terraform validate for #{workspace_name}"
        )
      end

      it "runs Terraform validate, with upgrade option" do
        env_config = {
          "min_servers" => 2,
          "max_servers" => 4,
          "aurora" => {
            "identifier" => "testaurora",
            "in_use_by" => [
              "test-service"
            ],
            "clusters_in_use" => {
              "production" => [
                "test"
              ],
              "staging" => [
                "test"
              ]
            },
            "minimum_size" => {
              "production" => 2,
              "staging" => 1
            },
            "maximum_size" => {
              "production" => 2,
              "staging" => 1
            },
            "engine" => "aurora-postgresql",
            "engine_version" => "11.9",
            "db_name" => "testapp",
            "port" => 5432,
            "maintenance_window" => "mon:19:00-mon:19:30",
            "backup_window" => "09:00-10:00",
            "backup_retention_period" => 31,
            "force_ssl" => true,
            "parameter_store_path_db_url_name" => "DATABASE_URL",
            "sql_backup_scheduled_task_environment_variables" => [
              {
                "name" => "foo",
                "value" => "bar"
              }
            ],
            "check_sql_backup_scheduled_task_environment_variables" => [
              {
                "name" => "foo",
                "value" => "bar"
              }
            ],
            "sync_sql_backup_to_azure" => false,
            "replication_bucket_destination_arn" => "arn:aws:s3:::dest-bucket",
            "replication_kms_key_id" => "key-id"
          },
          "account_id" => 123456789012,
          "infrastructure_name" => "new-dedicated-cluster-id",
          "environment" => "staging",
          "dalmatian_role" => "dalmatian-read"
        }
        expect(terraform).to have_received(:validate).with(
          tfvars: env_config
        )
      end

      it "changes back to the app root directory" do
        expect(helper).to have_received(:change_to).with(Infrastructure::APP_ROOT)
      end
    end
  end
end
