def test_delete_removed_settings(self):
        '''
        Calls `delete_removed_settings` with connection subnets that are used by `REG_SETTING_RFDK_1` and `REG_SETTING_RFDK_2`,
        but only the source subnet for `REG_SETTING_RFDK_1` is added. Since the source subnet for `REG_SETTING_RFDK_2` is
        missing, we expect `REG_SETTING_RFDK_2` to be deleted.
        '''
        # GIVEN
        self.dl_secrets.run_str = Mock(return_value="Pass")
        connection_subnet_ids = [
            "subnet-aaaaaaa", # Used by REG_SETTING_RFDK_1
            "subnet-bbbbbbb", # Used by REG_SETTING_RFDK_2
            "subnet-ccccccc"
        ]
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-1111111", role="Client", registration_status="Registered"), # Used by REG_SETTING_RFDK_1
            subject.SourceSubnet(subnet_id="subnet-1234567", role="Server", registration_status="Pending")
        ]

        # WHEN
        subject.delete_removed_settings(self.dl_secrets, self.prior_rfdk_reg_settings, connection_subnet_ids, source_subnets)

        # THEN
        self.dl_secrets.run_str.assert_called_once_with(
            'DeleteLoadBalancerIdentityRegistrationSetting',
            RFDK_REG_SETTING_JSON_2["SettingsId"]
        )
    def test_create_multiple(self):
        # GIVEN
        connection_subnet_ids = [
            "subnet-ccccccc",
            "subnet-ddddddd"
        ]
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-3333333", role="Client", registration_status="Registered"),
            subject.SourceSubnet(subnet_id="subnet-4444444", role="Client", registration_status="Registered"),
        ]
        subnet_to_cidr = {
            "subnet-ccccccc": "10.10.0.0/16", # 10.10.*.*
            "subnet-ddddddd": "11.11.0.0/16", # 11.11.*.*
            "subnet-3333333": "96.0.0.0/5", # 96-103.*.*.*
            "subnet-4444444": "104.0.0.0/22", # 104.0.0-3.*
        }

        # WHEN
        subject.create_and_update_settings(self.dl_secrets, [], connection_subnet_ids, source_subnets, subnet_to_cidr)

        # THEN
        for connection_subnet_id in connection_subnet_ids:
            for source_subnet in source_subnets:
                expected = subject.LoadBalancerIdentityRegistrationSetting(
                    connection_ip_filter_type  = "IPv4Match",
                    connection_ip_filter_value = subject.cidr_to_ipv4_match(subnet_to_cidr[connection_subnet_id]),
                    source_ip_filter_type      = "IPv4Match",
                    source_ip_filter_value     = subject.cidr_to_ipv4_match(subnet_to_cidr[source_subnet.subnet_id]),
                    settings_id                = '', # Unused
                    settings_name              = f"RfdkSubnet|{connection_subnet_id}|{source_subnet.subnet_id}",
                    is_enabled                 = True,
                    default_status             = source_subnet.registration_status,
                    default_role               = source_subnet.role
                )
                self.dl_secrets.run_str.assert_any_call(
                    "CreateLoadBalancerIdentityRegistrationSetting",
                    expected.settings_name,
                    expected.connection_ip_filter_type,
                    expected.connection_ip_filter_value,
                    expected.source_ip_filter_type,
                    expected.source_ip_filter_value,
                    expected.default_role,
                    expected.default_status,
                    str(expected.is_enabled)
                )
    def test_parsing_complex_config(self):
        config = subject.parse_args([
            "--credentials", "arn:aws:secretsmanager:us-west-2:111122223333:secret:aes128-1a2b3c",
            "--region", "test-region",
            "--connection-subnet", "subnet-7e573",
            "--connection-subnet", "subnet-7e574",
            "--source-subnet", "subnet-50c31,Client,Registered",
            "--source-subnet", "subnet-50c32,Server,Pending"
        ])

        self.assertEqual(config.credentials, subject.AwsSecret(arn="arn:aws:secretsmanager:us-west-2:111122223333:secret:aes128-1a2b3c", region="us-west-2"))
        self.assertEqual(config.region, "test-region")
        self.assertListEqual(config.connection_subnet, [ "subnet-7e573", "subnet-7e574" ])
        self.assertListEqual(
            config.source_subnet,
            [
                subject.SourceSubnet(subnet_id="subnet-50c31", role="Client", registration_status="Registered"),
                subject.SourceSubnet(subnet_id="subnet-50c32", role="Server", registration_status="Pending")
            ]
        )
    def test_delete_no_removed_settings(self):
        '''
        Calls `delete_removed_settings` with the connection and source subnets used by `REG_SETTING_RFDK_1` and `REG_SETTING_RFDK_2`.
        Since both previously configured settings still exist, nothing should be deleted.
        '''
        # GIVEN
        self.dl_secrets.run_str = Mock(return_value="Pass")
        connection_subnet_ids = [
            "subnet-aaaaaaa", # Used by REG_SETTING_RFDK_1
            "subnet-bbbbbbb", # Used by REG_SETTING_RFDK_2
            "subnet-ccccccc"
        ]
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-1111111", role="Client", registration_status="Registered"), # Used by REG_SETTING_RFDK_1
            subject.SourceSubnet(subnet_id="subnet-2222222", role="Client", registration_status="Registered"), # Used by REG_SETTING_RFDK_2
            subject.SourceSubnet(subnet_id="subnet-1234567", role="Server", registration_status="Pending")
        ]

        # WHEN
        subject.delete_removed_settings(self.dl_secrets, self.prior_rfdk_reg_settings, connection_subnet_ids, source_subnets)

        # THEN
        self.dl_secrets.run_str.assert_not_called()
    def test_update(self):
        '''
        Calls `create_and_update_settings` with a connection subnet and source subnet that are currently used
        in an applied registration setting, but the role and registration status are different, so the existing
        registration setting should be updated.
        '''
        # GIVEN
        connection_subnet_ids = [
            "subnet-aaaaaaa" # Used by REG_SETTING_RFDK_1
        ]
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-1111111", role="Server", registration_status="Pending"), # ID ised by REG_SETTING_RFDK_1,
        ]
        subnet_to_cidr = {
            "subnet-aaaaaaa": "111.111.0.0/16", # "111.111.*.*" Used by REG_SETTING_RFDK_1
            "subnet-1111111": "123.123.123.0/24", # "123.123.123.*" # Used by REG_SETTING_RFDK_1
        }

        # WHEN
        subject.create_and_update_settings(self.dl_secrets, self.prior_rfdk_reg_settings, connection_subnet_ids, source_subnets, subnet_to_cidr)

        # THEN
        expected = subject.LoadBalancerIdentityRegistrationSetting(
            # We expect RFDK_REG_SETTING_1 to be updated
            settings_id=RFDK_REG_SETTING_1.settings_id,
            connection_ip_filter_type=RFDK_REG_SETTING_1.connection_ip_filter_type,
            connection_ip_filter_value=subject.cidr_to_ipv4_match(subnet_to_cidr[connection_subnet_ids[0]]),
            source_ip_filter_type=RFDK_REG_SETTING_1.source_ip_filter_type,
            source_ip_filter_value=subject.cidr_to_ipv4_match(subnet_to_cidr[source_subnets[0].subnet_id]),
            settings_name=RFDK_REG_SETTING_1.settings_name,
            is_enabled=True,
            default_status="Pending",
            default_role="Server"
        )

        self.dl_secrets.run_str.assert_called_once_with(
            "UpdateLoadBalancerIdentityRegistrationSetting",
            expected.settings_id,
            expected.settings_name,
            expected.connection_ip_filter_type,
            expected.connection_ip_filter_value,
            expected.source_ip_filter_type,
            expected.source_ip_filter_value,
            expected.default_role,
            expected.default_status,
            str(expected.is_enabled),
        )
    def test_create(self):
        '''
        Calls `create_and_update_settings` a connection subnet ID that's used in one of the current registration
        settings and a source subnet ID that is used in a different registration setting. Since the two subnets aren't
        used together in a registration setting, a new one should be created.
        '''
        # GIVEN
        connection_subnet_ids = [
            "subnet-aaaaaaa" # Used by REG_SETTING_RFDK_1
        ]
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-2222222", role="Client", registration_status="Registered"), # Used by REG_SETTING_RFDK_2,
        ]
        subnet_to_cidr = {
            "subnet-aaaaaaa": "111.111.0.0/16", # "111.111.*.*" Used by REG_SETTING_RFDK_1
            "subnet-2222222": "3.3.0.0/18", # "3.3.0-63.*" # Used by REG_SETTING_RFDK_2
        }

        # WHEN
        subject.create_and_update_settings(self.dl_secrets, self.prior_rfdk_reg_settings, connection_subnet_ids, source_subnets, subnet_to_cidr)

        # THEN
        expected = subject.LoadBalancerIdentityRegistrationSetting(
            connection_ip_filter_type="IPv4Match",
            connection_ip_filter_value=subject.cidr_to_ipv4_match(subnet_to_cidr[connection_subnet_ids[0]]),
            source_ip_filter_type="IPv4Match",
            source_ip_filter_value=subject.cidr_to_ipv4_match(subnet_to_cidr[source_subnets[0].subnet_id]),
            settings_id="", # Ignored
            settings_name=f"RfdkSubnet|{connection_subnet_ids[0]}|{source_subnets[0].subnet_id}",
            is_enabled=True,
            default_status=source_subnets[0].registration_status,
            default_role=source_subnets[0].role
        )

        self.dl_secrets.run_str.assert_called_once_with(
            "CreateLoadBalancerIdentityRegistrationSetting",
            expected.settings_name,
            expected.connection_ip_filter_type,
            expected.connection_ip_filter_value,
            expected.source_ip_filter_type,
            expected.source_ip_filter_value,
            expected.default_role,
            expected.default_status,
            str(expected.is_enabled),
        )
    def test_create_and_update_no_connection_subnets(self):
        '''
        Calls `create_and_update_settings` with no connection subnet ID's, so no registration settings should be created or updated
        '''
        # GIVEN
        connection_subnet_ids = []
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-2222222", role="Client", registration_status="Registered"), # Used by REG_SETTING_RFDK_2
        ]
        subnet_to_cidr = {
            "subnet-2222222": "3.3.0.0/18", # "3.3.0-63.*" # Used by REG_SETTING_RFDK_2
        }

        # WHEN
        subject.create_and_update_settings(self.dl_secrets, self.prior_rfdk_reg_settings, connection_subnet_ids, source_subnets, subnet_to_cidr)

        # THEN
        self.dl_secrets.run_str.assert_not_called()
    def test_create_and_update_no_changes(self):
        '''
        Calls `create_and_update_settings` with a connection subnet and source subnet that are currently used
        in an applied registration setting, with the same role and registration status, so the existing
        registration setting shouldn't be changed..
        '''
        # GIVEN
        connection_subnet_ids = [
            "subnet-aaaaaaa" # Used by REG_SETTING_RFDK_1
        ]
        source_subnets = [
            subject.SourceSubnet(subnet_id="subnet-1111111", role="Client", registration_status="Registered"), # ID ised by REG_SETTING_RFDK_1,
        ]
        subnet_to_cidr = {
            "subnet-aaaaaaa": "111.111.0.0/16", # "111.111.*.*" Used by REG_SETTING_RFDK_1
            "subnet-1111111": "123.123.123.0/24", # "123.123.123.*" # Used by REG_SETTING_RFDK_1
        }

        # WHEN
        subject.create_and_update_settings(self.dl_secrets, self.prior_rfdk_reg_settings, connection_subnet_ids, source_subnets, subnet_to_cidr)

        # THEN
        self.dl_secrets.run_str.assert_not_called()