Ejemplo n.º 1
0
 def test_groups_list_nonexistent_deployment(self):
     expected_message = ('Deployment nonexistent-dep not found')
     error = CloudifyClientError('')
     error.status_code = 404
     self.client.deployments.get = MagicMock(side_effect=error)
     self._assert_ex("cfy groups list -d nonexistent-dep", expected_message)
Ejemplo n.º 2
0
 def raise_client_error():
     raise CloudifyClientError('this is an IOError')
Ejemplo n.º 3
0
#    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    * See the License for the specific language governing permissions and
#    * limitations under the License.

import mock

from cloudify.state import current_ctx
from cloudify.exceptions import NonRecoverableError
from cloudify_rest_client.exceptions import CloudifyClientError

from .client_mock import MockCloudifyRestClient
from .base import DeploymentProxyTestBase
from ..tasks import create_deployment, delete_deployment

REST_CLIENT_EXCEPTION = \
    mock.MagicMock(side_effect=CloudifyClientError('Mistake'))


class TestDeployment(DeploymentProxyTestBase):

    sleep_mock = None

    def setUp(self):
        super(TestDeployment, self).setUp()
        mock_sleep = mock.MagicMock()
        self.sleep_mock = mock.patch('time.sleep', mock_sleep)
        self.sleep_mock.start()

    def tearDown(self):
        if self.sleep_mock:
            self.sleep_mock.stop()
Ejemplo n.º 4
0
class TestPropertiesUpdateDefaultMergeHandler(unittest.TestCase):
    ERR_CONFLICT = CloudifyClientError('conflict', status_code=409)

    def test_merge_handler_noconflict(self):
        """The merge builtin handler adds properties that are not present.

        If a property was added locally, but isn't in the storage version,
        it can be added.
        """
        instance = NodeInstance('id', 'node_id', {'value': 1})

        def mock_update(instance):
            # we got both properties merged - the locally added one
            # and the server one
            self.assertEqual({
                'othervalue': 1,
                'value': 1
            }, instance.runtime_properties)

        ep = mock.Mock(
            **{
                'get_node_instance.return_value': instance,
                'update_node_instance.side_effect': mock_update
            })

        ctx = _context_with_endpoint(ep)
        ctx.runtime_properties['othervalue'] = 1
        ctx.update(conflict_handlers.simple_merge_handler)

        ep.update_node_instance.assert_called_once_with(instance)

    def test_merge_handler_repeated_property(self):
        """Merge handler won't overwrite already existing properties.

        First fetch returns value=1; locally change that to 2 and try to
        update. However server says that's a conflict, and now says value=5.
        Merge handler decides it can't merge and errors out.
        """
        instance = NodeInstance('id', 'node_id', {'value': 1})

        ep = mock.Mock(
            **{
                'get_node_instance.return_value': instance,
                'update_node_instance.side_effect': self.ERR_CONFLICT
            })
        ctx = _context_with_endpoint(ep)
        ctx.runtime_properties['value'] = 2

        # in the meantime, server's version changed! value is now 5
        ep.get_node_instance.return_value = NodeInstance(
            'id', 'node_id', {'value': 5})

        try:
            ctx.update(conflict_handlers.simple_merge_handler)
        except ValueError:
            pass
        else:
            self.fail('merge handler should fail to merge repeated properties')

        self.assertEqual(1, len(ep.update_node_instance.mock_calls))

    def test_merge_handler_conflict_resolved(self):
        """Merge handler can resolve conflicts, adding new properties.

        First fetch returns instance without the 'value' property.
        Handler adds the locally-added 'othervalue' and tries updating.
        That's a conflict, because now the server version has the 'value'
        property. Handler refetches, and is able to merge.
        """

        instances = [
            NodeInstance('id', 'node_id'),
            NodeInstance('id', 'node_id', {'value': 1})
        ]

        def mock_update(instance):
            if 'value' not in instance.runtime_properties:
                raise self.ERR_CONFLICT
            self.assertEqual({
                'othervalue': 1,
                'value': 1
            }, instance.runtime_properties)

        ep = mock.Mock(
            **{
                'get_node_instance.side_effect': instances,
                'update_node_instance.side_effect': mock_update
            })

        ctx = _context_with_endpoint(ep)
        ctx.runtime_properties['othervalue'] = 1
        # at this point we don't know about the 'value' property yet
        ctx.update(conflict_handlers.simple_merge_handler)

        self.assertEqual(2, len(ep.update_node_instance.mock_calls))
Ejemplo n.º 5
0
 def raise_client_error():
     raise CloudifyClientError('CloudifyClientError')
Ejemplo n.º 6
0
class TestPropertiesUpdate(testtools.TestCase):
    ERR_CONFLICT = CloudifyClientError('conflict', status_code=409)

    def test_update(self):
        """.update() without a handler sends the changed runtime properties."""
        def mock_update(instance):
            self.assertEqual({'foo': 42}, instance.runtime_properties)

        instance = NodeInstance('id', 'node_id')
        ep = mock.Mock(
            **{
                'get_node_instance.return_value': instance,
                'update_node_instance.side_effect': mock_update
            })
        ctx = _context_with_endpoint(ep)
        ctx.runtime_properties['foo'] = 42
        ctx.update()

        ep.update_node_instance.assert_called_once_with(instance)

    def test_update_conflict_no_handler(self):
        """Version conflict without a handler function aborts the operation."""
        instance = NodeInstance('id', 'node_id')

        ep = mock.Mock(
            **{
                'get_node_instance.return_value': instance,
                'update_node_instance.side_effect': self.ERR_CONFLICT
            })

        ctx = _context_with_endpoint(ep)
        ctx.runtime_properties['foo'] = 42

        try:
            ctx.update()
        except CloudifyClientError as e:
            self.assertEqual(409, e.status_code)
        else:
            self.fail('ctx.update() has hidden the 409 error')

    def test_update_conflict_simple_handler(self):
        """On a conflict, the handler will be called until it succeeds.

        The simple handler function in this test will just increase the
        runtime property value by 1 each call. When the value reaches 5,
        the mock update method will at last allow it to save.
        """
        # each next call of the mock .get_node_instance will return subsequent
        # instances: each time the runtime property is changed
        instances = [
            NodeInstance('id', 'node_id', {'value': i}) for i in range(5)
        ]

        def mock_update(instance):
            if instance.runtime_properties.get('value', 0) < 5:
                raise self.ERR_CONFLICT

        ep = mock.Mock(
            **{
                'get_node_instance.side_effect': instances,
                'update_node_instance.side_effect': mock_update
            })

        ctx = _context_with_endpoint(ep)
        ctx.runtime_properties['value'] = 1

        def _handler(previous, next_props):
            # the "previous" argument is always the props as they were before
            # .update() was called
            self.assertEqual(previous, {'value': 1})
            return {'value': next_props['value'] + 1}

        handler = mock.Mock(side_effect=_handler)  # Mock() for recording calls
        ctx.update(handler)

        self.assertEqual(5, len(handler.mock_calls))
        self.assertEqual(5, len(ep.update_node_instance.mock_calls))
Ejemplo n.º 7
0
 def mock_return(*_, **__):
     raise CloudifyClientError('Mistake')
Ejemplo n.º 8
0
 def mock_return(*args, **kwargs):
     raise CloudifyClientError('Mistake')
Ejemplo n.º 9
0
 def test_deployments_delete(self):
     self.client.deployments.delete = MagicMock()
     self.client.executions.list = MagicMock(
         side_effect=CloudifyClientError(
             '`Deployment` with ID `my-dep` was not found'))
     self.invoke('cfy deployments delete my-dep')
Ejemplo n.º 10
0
 def test_delete_secret_Error(self):
     mock_client = mock.MagicMock(side_effect=CloudifyClientError("e"))
     with mock.patch('cloudify.manager.get_rest_client', mock_client):
         self.assertRaises(NonRecoverableError, _delete_secret, 'k')