from unittest import TestCase, mock
from click.testing import CliRunner
from kfk.commands.acls import kfk
from kfk.kubectl_command_builder import Kubectl


class TestKfkAcls(TestCase):

    def setUp(self):
        self.runner = CliRunner()
        self.kafka_cluster = "my-cluster"
        self.namespace = "kafka"
        self.topic = "my-topic"
        self.group = "my-group"
        self.user = "my-user"

    @mock.patch('kfk.commands.acls.os')
    def test_list_all_acls(self, mock_os):
        result = self.runner.invoke(kfk, ['acls', '--list', '-n', self.namespace, '-c', self.kafka_cluster])
        assert result.exit_code == 0
        native_command = "bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:12181 --list  "
        mock_os.system.assert_called_with(
            Kubectl().exec("-it", "{kafka_cluster}-zookeeper-0").container("zookeeper").namespace(
                self.namespace).exec_command(native_command).build().format(kafka_cluster=self.kafka_cluster))

    @mock.patch('kfk.commands.acls.os')
    def test_list_topic_acls(self, mock_os):
        result = self.runner.invoke(kfk, ['acls', '--list', '--topic', self.topic, '-n', self.namespace, '-c',
                                          self.kafka_cluster])
        assert result.exit_code == 0
        native_command = "bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:12181 --list --topic " \
                         "{topic} ".format(topic=self.topic)
        mock_os.system.assert_called_with(
            Kubectl().exec("-it", "{kafka_cluster}-zookeeper-0").container("zookeeper").namespace(
                self.namespace).exec_command(native_command).build().format(kafka_cluster=self.kafka_cluster))

    @mock.patch('kfk.commands.acls.os')
    def test_list_group_acls(self, mock_os):
        result = self.runner.invoke(kfk, ['acls', '--list', '--group', self.group, '-n', self.namespace, '-c',
                                          self.kafka_cluster])
        assert result.exit_code == 0
        native_command = "bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:12181 --list  --group" \
                         " {group}".format(group=self.group)
        mock_os.system.assert_called_with(
            Kubectl().exec("-it", "{kafka_cluster}-zookeeper-0").container("zookeeper").namespace(
                self.namespace).exec_command(native_command).build().format(kafka_cluster=self.kafka_cluster))

    @mock.patch('kfk.commands.acls.os')
    def test_add_acls_without_principal(self, mock_os):
        result = self.runner.invoke(kfk, ['acls', '--add', '--topic', self.topic, '-n', self.namespace, '-c',
                                          self.kafka_cluster])
        assert result.exit_code == 2

    @mock.patch('kfk.commands.users.create_temp_file')
    @mock.patch('kfk.commons.get_resource_yaml')
    @mock.patch('kfk.commands.users.os')
    def test_add_topic_acl(self, mock_os, mock_get_resource_yaml, mock_create_temp_file):
        with open(r'files/yaml/user_with_authentication_tls.yaml') as file:
            user_yaml = file.read()
            mock_get_resource_yaml.return_value = user_yaml

            result = self.runner.invoke(kfk,
                                        ['acls', '--add', '--topic', self.topic, '--allow-principal',
                                         'User:' + self.user, '--operation', 'Read', '-n', self.namespace, '-c',
                                         self.kafka_cluster])
            assert result.exit_code == 0

            with open(r'files/yaml/user_with_authorization_with_one_topic_acl.yaml') as file:
                expected_user_yaml = file.read()
                result_user_yaml = mock_create_temp_file.call_args[0][0]
                assert expected_user_yaml == result_user_yaml

    @mock.patch('kfk.commands.users.create_temp_file')
    @mock.patch('kfk.commons.get_resource_yaml')
    @mock.patch('kfk.commands.users.os')
    def test_remove_topic_acl(self, mock_os, mock_get_resource_yaml, mock_create_temp_file):
        with open(r'files/yaml/user_with_authorization_with_one_topic_acl.yaml') as file:
            user_yaml = file.read()
            mock_get_resource_yaml.return_value = user_yaml

            result = self.runner.invoke(kfk,
                                        ['acls', '--remove', '--topic', self.topic, '--allow-principal',
                                         'User:' + self.user, '--operation', 'Read', '-n', self.namespace, '-c',
                                         self.kafka_cluster])
            assert result.exit_code == 0

            with open(r'files/yaml/user_with_authentication_tls.yaml') as file:
                expected_user_yaml = file.read()
                result_user_yaml = mock_create_temp_file.call_args[0][0]
                assert expected_user_yaml == result_user_yaml

    @mock.patch('kfk.commands.users.create_temp_file')
    @mock.patch('kfk.commons.get_resource_yaml')
    @mock.patch('kfk.commands.users.os')
    def test_add_topic_acl_to_one_acl(self, mock_os, mock_get_resource_yaml, mock_create_temp_file):
        with open(r'files/yaml/user_with_authorization_with_one_topic_acl.yaml') as file:
            user_yaml = file.read()
            mock_get_resource_yaml.return_value = user_yaml

            result = self.runner.invoke(kfk,
                                        ['acls', '--add', '--topic', self.topic, '--allow-principal',
                                         'User:' + self.user, '--operation', 'Write', '-n', self.namespace, '-c',
                                         self.kafka_cluster])
            assert result.exit_code == 0

            with open(r'files/yaml/user_with_authorization_with_two_topic_acls.yaml') as file:
                expected_user_yaml = file.read()
                result_user_yaml = mock_create_temp_file.call_args[0][0]
                assert expected_user_yaml == result_user_yaml

    @mock.patch('kfk.commands.users.create_temp_file')
    @mock.patch('kfk.commons.get_resource_yaml')
    @mock.patch('kfk.commands.users.os')
    def test_remove_topic_acl_from_two_acls(self, mock_os, mock_get_resource_yaml, mock_create_temp_file):
        with open(r'files/yaml/user_with_authorization_with_two_topic_acls.yaml') as file:
            user_yaml = file.read()
            mock_get_resource_yaml.return_value = user_yaml

            result = self.runner.invoke(kfk,
                                        ['acls', '--remove', '--topic', self.topic, '--allow-principal',
                                         'User:' + self.user, '--operation', 'Write', '-n', self.namespace, '-c',
                                         self.kafka_cluster])
            assert result.exit_code == 0

            with open(r'files/yaml/user_with_authorization_with_one_topic_acl.yaml') as file:
                expected_user_yaml = file.read()
                result_user_yaml = mock_create_temp_file.call_args[0][0]
                assert expected_user_yaml == result_user_yaml

    @mock.patch('kfk.commands.users.create_temp_file')
    @mock.patch('kfk.commons.get_resource_yaml')
    @mock.patch('kfk.commands.users.os')
    def test_add_topic_acl_with_two_operations(self, mock_os, mock_get_resource_yaml, mock_create_temp_file):
        with open(r'files/yaml/user_with_authorization_with_one_topic_acl.yaml') as file:
            user_yaml = file.read()
            mock_get_resource_yaml.return_value = user_yaml

            result = self.runner.invoke(kfk,
                                        ['acls', '--add', '--topic', self.topic, '--allow-principal',
                                         'User:' + self.user, '--operation', 'Write', '--operation', 'Describe', '-n',
                                         self.namespace, '-c', self.kafka_cluster])
            assert result.exit_code == 0

            with open(r'files/yaml/user_with_authorization_with_three_topic_acls.yaml') as file:
                expected_user_yaml = file.read()
                result_user_yaml = mock_create_temp_file.call_args[0][0]
                assert expected_user_yaml == result_user_yaml

    @mock.patch('kfk.commands.users.create_temp_file')
    @mock.patch('kfk.commons.get_resource_yaml')
    @mock.patch('kfk.commands.users.os')
    def test_add_group_acl(self, mock_os, mock_get_resource_yaml, mock_create_temp_file):
        with open(r'files/yaml/user_with_authorization_with_one_topic_acl.yaml') as file:
            user_yaml = file.read()
            mock_get_resource_yaml.return_value = user_yaml

            result = self.runner.invoke(kfk,
                                        ['acls', '--add', '--group', self.group, '--allow-principal',
                                         'User:' + self.user, '--operation', 'Read', '-n', self.namespace, '-c',
                                         self.kafka_cluster])
            assert result.exit_code == 0

            with open(r'files/yaml/user_with_authorization_with_one_topic_and_one_group_acls.yaml') as file:
                expected_user_yaml = file.read()
                result_user_yaml = mock_create_temp_file.call_args[0][0]
                assert expected_user_yaml == result_user_yaml
