<commit_before># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Tests for ``flocker.node._deploy``.
"""

from uuid import uuid4

from twisted.internet.defer import fail, FirstError, succeed
from twisted.trial.unittest import SynchronousTestCase
from twisted.python.filepath import FilePath

from .. import (Deployer, Application, DockerImage, Deployment, Node,
                StateChanges, Port)
from .._model import AttachedVolume
from ..gear import GearClient, FakeGearClient, AlreadyExists, Unit, PortMap
from ...route import Proxy, make_memory_network
from ...route._iptables import HostNetwork
from ...volume.service import Volume
from ...volume.testtools import create_volume_service


class DeployerAttributesTests(SynchronousTestCase):
    """
    Tests for attributes and initialiser arguments of `Deployer`.
    """
    def test_gear_client_default(self):
        """
        ``Deployer._gear_client`` is a ``GearClient`` by default.
        """
        self.assertIsInstance(
            Deployer(None)._gear_client,
            GearClient
        )

    def test_gear_override(self):
        """
        ``Deployer._gear_client`` can be overridden in the constructor.
        """
        dummy_gear_client = object()
        self.assertIs(
            dummy_gear_client,
            Deployer(create_volume_service(self),
                     gear_client=dummy_gear_client)._gear_client
        )

    def test_network_default(self):
        """
        ``Deployer._network`` is a ``HostNetwork`` by default.
        """
        self.assertIsInstance(Deployer(None)._network, HostNetwork)

    def test_network_override(self):
        """
        ``Deployer._network`` can be overridden in the constructor.
        """
        dummy_network = object()
        self.assertIs(
            dummy_network,
            Deployer(create_volume_service(self),
                     network=dummy_network)._network
        )


class DeployerStartApplicationTests(SynchronousTestCase):
    """
    Tests for `Deployer.start_application`.
    """
    def test_start(self):
        """
        `Deployer.start_application` accepts an application object and returns
        a `Deferred` which fires when the `gear` unit has been added and
        started.
        """
        fake_gear = FakeGearClient()
        api = Deployer(create_volume_service(self), gear_client=fake_gear)
        docker_image = DockerImage(repository=u'clusterhq/flocker',
                                   tag=u'release-14.0')
        ports = frozenset([Port(internal_port=80, external_port=8080)])
        application = Application(
            name=u'site-example.com',
            image=docker_image,
            ports=ports,
        )
        start_result = api.start_application(application=application)
        exists_result = fake_gear.exists(unit_name=application.name)

        port_maps = [PortMap(internal_port=80, external_port=8080)]
        self.assertEqual(
            (None, True, docker_image.full_name, port_maps),
            (self.successResultOf(start_result),
             self.successResultOf(exists_result),
             fake_gear._units[application.name].container_image,
             fake_gear._units[application.name].ports)
        )

    def test_already_exists(self):
        """
        ``Deployer.start_application`` returns a `Deferred` which errbacks with
        an ``AlreadyExists`` error if there is already a unit with the supplied
        application name.
        """
        api = Deployer(create_volume_service(self),
                       gear_client=FakeGearClient())
        application = Application(
            name=b'site-example.com',
            image=DockerImage(repository=u'clusterhq/flocker',
                              tag=u'release-14.0')
        )

        result1 = api.start_application(application=application)
        self.successResultOf(result1)

        result2 = api.start_application(application=application)
        self.failureResultOf(result2, AlreadyExists)

    def test_volume_exposed_on_start(self):
        """
        ``Deployer.start_application`` exposes an application's volume before
        it is started.
        """
        volume_service = create_volume_service(self)
        fake_gear = FakeGearClient()
        deployer = Deployer(volume_service, fake_gear)
        docker_image = DockerImage.from_string(u"busybox")
        application = Application(
            name=u'site-example.com',
            image=docker_image,
            volume=AttachedVolume(name=u'site-example.com',
                                  mountpoint=FilePath(b"/var"))
        )

        # This would be better to test with a verified fake:
        # https://github.com/ClusterHQ/flocker/issues/234
        exposed = []
        def expose_to_docker(volume, mount_path):
            # We check for existence of unit so we can ensure exposure
            # happens *before* the unit is started:
            exposed.append((volume, mount_path, self.successResultOf(
                fake_gear.exists(u"site-example.com"))))
            return succeed(None)
        self.patch(Volume, "expose_to_docker", expose_to_docker)

        deployer.start_application(application)
        self.assertEqual(exposed, [(volume_service.get(u"site-example.com"),
                                    FilePath(b"/var"), False)])


class DeployerStopApplicationTests(SynchronousTestCase):
    """
    Tests for ``Deployer.stop_application``.
    """
    def test_stop(self):
        """
        ``Deployer.stop_application`` accepts an application object and returns
        a `Deferred` which fires when the `gear` unit has been removed.
        """
        fake_gear = FakeGearClient()
        api = Deployer(create_volume_service(self), gear_client=fake_gear)
        application = Application(
            name=b'site-example.com',
            image=DockerImage(repository=u'clusterhq/flocker',
                              tag=u'release-14.0')
        )

        api.start_application(application=application)
        existed = fake_gear.exists(application.name)
        stop_result = api.stop_application(application=application)
        exists_result = fake_gear.exists(unit_name=application.name)

        self.assertEqual(
            (None, True, False),
            (self.successResultOf(stop_result),
             self.successResultOf(existed),
             self.successResultOf(exists_result))
        )

    def test_does_not_exist(self):
        """
        ``Deployer.stop_application`` does not errback if the application does
        not exist.
        """
        api = Deployer(create_volume_service(self),
                       gear_client=FakeGearClient())
        application = Application(
            name=b'site-example.com',
            image=DockerImage(repository=u'clusterhq/flocker',
                              tag=u'release-14.0')
        )
        result = api.stop_application(application=application)
        result = self.successResultOf(result)

        self.assertIs(None, result)

    def test_volume_unexposed(self):
        """
        ``Deployer.stop_application`` removes an application's volume from
        Docker after it is stopped.
        """
        volume_service = create_volume_service(self)
        fake_gear = FakeGearClient()
        deployer = Deployer(volume_service, fake_gear)
        docker_image = DockerImage.from_string(u"busybox")
        application = Application(
            name=u'site-example.com',
            image=docker_image,
            volume=AttachedVolume(name=u'site-example.com',
                                  mountpoint=FilePath(b"/var"))
        )

        # This would be better to test with a verified fake:
        # https://github.com/ClusterHQ/flocker/issues/234
        self.patch(Volume, "expose_to_docker", lambda *args: succeed(None))
        removed = []
        def remove_from_docker(volume):
            # We check for existence of unit so we can ensure exposure
            # happens *after* the unit is stopped:<commit_msg>Lint fixes.<commit_after># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Tests for ``flocker.node._deploy``.
"""

from uuid import uuid4

from twisted.internet.defer import fail, FirstError, succeed
from twisted.trial.unittest import SynchronousTestCase
from twisted.python.filepath import FilePath

from .. import (Deployer, Application, DockerImage, Deployment, Node,
                StateChanges, Port)
from .._model import AttachedVolume
from ..gear import GearClient, FakeGearClient, AlreadyExists, Unit, PortMap
from ...route import Proxy, make_memory_network
from ...route._iptables import HostNetwork
from ...volume.service import Volume
from ...volume.testtools import create_volume_service


class DeployerAttributesTests(SynchronousTestCase):
    """
    Tests for attributes and initialiser arguments of `Deployer`.
    """
    def test_gear_client_default(self):
        """
        ``Deployer._gear_client`` is a ``GearClient`` by default.
        """
        self.assertIsInstance(
            Deployer(None)._gear_client,
            GearClient
        )

    def test_gear_override(self):
        """
        ``Deployer._gear_client`` can be overridden in the constructor.
        """
        dummy_gear_client = object()
        self.assertIs(
            dummy_gear_client,
            Deployer(create_volume_service(self),
                     gear_client=dummy_gear_client)._gear_client
        )

    def test_network_default(self):
        """
        ``Deployer._network`` is a ``HostNetwork`` by default.
        """
        self.assertIsInstance(Deployer(None)._network, HostNetwork)

    def test_network_override(self):
        """
        ``Deployer._network`` can be overridden in the constructor.
        """
        dummy_network = object()
        self.assertIs(
            dummy_network,
            Deployer(create_volume_service(self),
                     network=dummy_network)._network
        )


class DeployerStartApplicationTests(SynchronousTestCase):
    """
    Tests for `Deployer.start_application`.
    """
    def test_start(self):
        """
        `Deployer.start_application` accepts an application object and returns
        a `Deferred` which fires when the `gear` unit has been added and
        started.
        """
        fake_gear = FakeGearClient()
        api = Deployer(create_volume_service(self), gear_client=fake_gear)
        docker_image = DockerImage(repository=u'clusterhq/flocker',
                                   tag=u'release-14.0')
        ports = frozenset([Port(internal_port=80, external_port=8080)])
        application = Application(
            name=u'site-example.com',
            image=docker_image,
            ports=ports,
        )
        start_result = api.start_application(application=application)
        exists_result = fake_gear.exists(unit_name=application.name)

        port_maps = [PortMap(internal_port=80, external_port=8080)]
        self.assertEqual(
            (None, True, docker_image.full_name, port_maps),
            (self.successResultOf(start_result),
             self.successResultOf(exists_result),
             fake_gear._units[application.name].container_image,
             fake_gear._units[application.name].ports)
        )

    def test_already_exists(self):
        """
        ``Deployer.start_application`` returns a `Deferred` which errbacks with
        an ``AlreadyExists`` error if there is already a unit with the supplied
        application name.
        """
        api = Deployer(create_volume_service(self),
                       gear_client=FakeGearClient())
        application = Application(
            name=b'site-example.com',
            image=DockerImage(repository=u'clusterhq/flocker',
                              tag=u'release-14.0')
        )

        result1 = api.start_application(application=application)
        self.successResultOf(result1)

        result2 = api.start_application(application=application)
        self.failureResultOf(result2, AlreadyExists)

    def test_volume_exposed_on_start(self):
        """
        ``Deployer.start_application`` exposes an application's volume before
        it is started.
        """
        volume_service = create_volume_service(self)
        fake_gear = FakeGearClient()
        deployer = Deployer(volume_service, fake_gear)
        docker_image = DockerImage.from_string(u"busybox")
        application = Application(
            name=u'site-example.com',
            image=docker_image,
            volume=AttachedVolume(name=u'site-example.com',
                                  mountpoint=FilePath(b"/var"))
        )

        # This would be better to test with a verified fake:
        # https://github.com/ClusterHQ/flocker/issues/234
        exposed = []

        def expose_to_docker(volume, mount_path):
            # We check for existence of unit so we can ensure exposure
            # happens *before* the unit is started:
            exposed.append((volume, mount_path, self.successResultOf(
                fake_gear.exists(u"site-example.com"))))
            return succeed(None)
        self.patch(Volume, "expose_to_docker", expose_to_docker)

        deployer.start_application(application)
        self.assertEqual(exposed, [(volume_service.get(u"site-example.com"),
                                    FilePath(b"/var"), False)])


class DeployerStopApplicationTests(SynchronousTestCase):
    """
    Tests for ``Deployer.stop_application``.
    """
    def test_stop(self):
        """
        ``Deployer.stop_application`` accepts an application object and returns
        a `Deferred` which fires when the `gear` unit has been removed.
        """
        fake_gear = FakeGearClient()
        api = Deployer(create_volume_service(self), gear_client=fake_gear)
        application = Application(
            name=b'site-example.com',
            image=DockerImage(repository=u'clusterhq/flocker',
                              tag=u'release-14.0')
        )

        api.start_application(application=application)
        existed = fake_gear.exists(application.name)
        stop_result = api.stop_application(application=application)
        exists_result = fake_gear.exists(unit_name=application.name)

        self.assertEqual(
            (None, True, False),
            (self.successResultOf(stop_result),
             self.successResultOf(existed),
             self.successResultOf(exists_result))
        )

    def test_does_not_exist(self):
        """
        ``Deployer.stop_application`` does not errback if the application does
        not exist.
        """
        api = Deployer(create_volume_service(self),
                       gear_client=FakeGearClient())
        application = Application(
            name=b'site-example.com',
            image=DockerImage(repository=u'clusterhq/flocker',
                              tag=u'release-14.0')
        )
        result = api.stop_application(application=application)
        result = self.successResultOf(result)

        self.assertIs(None, result)

    def test_volume_unexposed(self):
        """
        ``Deployer.stop_application`` removes an application's volume from
        Docker after it is stopped.
        """
        volume_service = create_volume_service(self)
        fake_gear = FakeGearClient()
        deployer = Deployer(volume_service, fake_gear)
        docker_image = DockerImage.from_string(u"busybox")
        application = Application(
            name=u'site-example.com',
            image=docker_image,
            volume=AttachedVolume(name=u'site-example.com',
                                  mountpoint=FilePath(b"/var"))
        )

        # This would be better to test with a verified fake:
        # https://github.com/ClusterHQ/flocker/issues/234
        self.patch(Volume, "expose_to_docker", lambda *args: succeed(None))
        removed = []

        def remove_from_docker(volume):
            # We check for existence of unit so we can ensure exposure
            # happens *after* the unit is stopped:
{'fraction_non_alphanumeric': 0.09512890431333663, 'fraction_numerical': 0.004338125929598414, 'mean_word_length': 2.350010379904505, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4018282', 'n_tokens_mistral': 4510, 'n_tokens_neox': 4348, 'n_words': 876}