Пример #1
0
 def test_edi_undeploy_model_by_id(self):
     with EDITestServer() as edi:
         with m_func('kubernetes.client.CoreV1Api.list_namespaced_service', 'demo_abc_model_1_0'), \
              m_func('kubernetes.client.CoreV1Api.read_namespaced_service', ApiException(404)), \
              m_func('kubernetes.client.ExtensionsV1beta1Api.read_namespaced_deployment',
                     ['demo_abc_model_1_0', ApiException(404)]), \
              m_func('kubernetes.client.apis.apps_v1beta1_api.AppsV1beta1Api.delete_namespaced_deployment',
                     'model_deleted'), \
              m_func('kubernetes.client.CoreV1Api.delete_namespaced_service', 'undeploy_done'), \
              mock.patch('legion.k8s.utils.build_client', return_value=None), \
              mock.patch('legion.k8s.enclave.Enclave.graphite_service', return_value=None):
             deployments = edi.edi_client.undeploy('demo-abc-model')
             self.assertIsInstance(deployments, list)
             self.assertEqual(len(deployments), 1)
             # Check undeployed model fields
             expected_result = {
                 'image': '127.0.0.1/legion/test-bare-model-api-model-1:0.9.0-20181106123540.560.3b9739a',
                 'model': 'demo-abc-model',
                 'version': '1.0',
                 'scale': 1,
                 'ready_replicas': 1,
                 'status': 'ok',
                 'namespace': 'debug-enclave'
             }
             actual_result = {
                 'image': deployments[0].image,
                 'model': deployments[0].model,
                 'version': deployments[0].version,
                 'scale': deployments[0].scale,
                 'ready_replicas': deployments[0].ready_replicas,
                 'status': deployments[0].status,
                 'namespace': deployments[0].namespace
             }
             self.assertDictEqual(expected_result, actual_result)
Пример #2
0
    def read_storage_class(self, name):
        if self.name == 'fail':
            raise ApiException('Get storage class fail')
        if self.name == '404' or name == '404':
            raise ApiException(reason='Not Found')

        my_response = namedtuple('my_response', 'metadata status')
        my_status = namedtuple(
            'my_status',
            'replicas available_replicas ready_replicas updated_replicas unavailable_replicas'
        )

        if self.name == 'test1':
            return my_response(metadata={},
                               status=my_status(replicas=3,
                                                available_replicas=2,
                                                ready_replicas=1,
                                                updated_replicas=None,
                                                unavailable_replicas=1))
        if self.name == 'test2' or name == 'test2':
            return my_response(metadata={},
                               status=my_status(replicas=1,
                                                available_replicas=1,
                                                ready_replicas=1,
                                                updated_replicas=1,
                                                unavailable_replicas=None))

        return my_response(metadata={'key1': 'value1'},
                           status={'key1': 'value1'})
Пример #3
0
def test_atomic_creation_of_interactive_session(sample_serial_workflow_in_db):
    """Test the correct creation of all objects related to an interactive
       sesison as well as writing the state to DB, either all should be done
       or nothing.."""
    mocked_k8s_client = Mock()
    mocked_k8s_client.create_namespaced_deployment =\
        Mock(side_effect=ApiException(
             reason='Error while creating deployment'))
    # Raise 404 when deleting Deployment, because it doesn't exist
    mocked_k8s_client.delete_namespaced_deployment =\
        Mock(side_effect=ApiException(
             reason='Not Found'))
    with patch.multiple('reana_workflow_controller.k8s',
                        current_k8s_extensions_v1beta1=mocked_k8s_client,
                        current_k8s_corev1_api_client=DEFAULT) as mocks:
        try:
            kwrm = KubernetesWorkflowRunManager(sample_serial_workflow_in_db)
            if len(INTERACTIVE_SESSION_TYPES):
                kwrm.start_interactive_session(INTERACTIVE_SESSION_TYPES[0])
        except REANAInteractiveSessionError:
            mocks['current_k8s_corev1_api_client']\
                .delete_namespaced_service.assert_called_once()
            mocked_k8s_client.delete_namespaced_ingress.assert_called_once()
            mocked_k8s_client.delete_namespaced_deployment.assert_called_once()
            assert sample_serial_workflow_in_db.interactive_session is None
Пример #4
0
    def read_namespaced_job(self, name, namespace):
        if self.name == 'fail':
            raise ApiException('Get daemonset fail')
        if self.name == '404':
            raise ApiException(reason='Not Found')

        my_response = namedtuple('my_response', 'metadata status')
        my_status = namedtuple('my_status', 'failed conditions')

        if self.name == 'test1':
            return my_response(metadata={},
                               status=my_status(failed='Failed',
                                                conditions=[]))
        if self.name == 'test2':
            my_conditions = namedtuple('my_conditions', 'type')
            return my_response(metadata={},
                               status=my_status(
                                   failed=None,
                                   conditions=[my_conditions(type='Failed')]))
        if self.name == 'test3':
            my_conditions = namedtuple('my_conditions', 'type')
            return my_response(
                metadata={},
                status=my_status(failed=None,
                                 conditions=[my_conditions(type='Complete')]))

        return my_response(metadata={'key1': 'value1'},
                           status={'key1': 'value1'})
Пример #5
0
    def read_namespaced_service(self, name, namespace, body=None):
        if self.name == 'fail':
            raise ApiException('Get service fail')
        if self.name == '404':
            raise ApiException(reason='Not Found')

        my_response = namedtuple('my_response', 'metadata status spec')
        my_status = namedtuple(
            'my_status',
            'replicas available_replicas ready_replicas updated_replicas unavailable_replicas'
        )
        my_spec = namedtuple('my_spec', 'ports')
        my_port = namedtuple('my_port', 'port name')

        if self.name == 'test1':
            return my_response(
                metadata={},
                spec=my_spec(ports=[my_port(port=123, name='test1')]),
                status=my_status(replicas=3,
                                 available_replicas=2,
                                 ready_replicas=1,
                                 updated_replicas=None,
                                 unavailable_replicas=1))
        if self.name == 'test2':
            return my_response(metadata={},
                               spec=my_spec(ports=[]),
                               status=my_status(replicas=1,
                                                available_replicas=1,
                                                ready_replicas=1,
                                                updated_replicas=1,
                                                unavailable_replicas=None))

        return my_response(metadata={'key1': 'value1'},
                           status={'key1': 'value1'},
                           spec={})
Пример #6
0
    def read_namespaced_deployment(self, name, namespace):
        if self.name == 'fail':
            raise ApiException('Get deployment fail')
        if self.name == '404' or name == '404':
            raise ApiException(reason='Not Found')

        my_response = namedtuple('my_response', 'metadata status spec')
        my_status = namedtuple(
            'my_status',
            'replicas available_replicas ready_replicas updated_replicas unavailable_replicas'
        )
        my_spec = namedtuple('my_spec', 'replicas')
        if self.name == 'test1':
            return my_response(metadata={},
                               spec=my_spec(replicas=3),
                               status=my_status(replicas=3,
                                                available_replicas=2,
                                                ready_replicas=1,
                                                updated_replicas=None,
                                                unavailable_replicas=1))
        if self.name == 'test2' or name == 'test2':
            return my_response(metadata={},
                               spec=my_spec(replicas=1),
                               status=my_status(replicas=1,
                                                available_replicas=1,
                                                ready_replicas=1,
                                                updated_replicas=1,
                                                unavailable_replicas=None))

        return my_response(metadata={'key1': 'value1'},
                           status={'key1': 'value1'},
                           spec={'key1': 'value1'})
Пример #7
0
    def read_namespaced_daemon_set(self, name, namespace):
        if self.name == 'fail':
            raise ApiException('Get daemonset fail')
        if self.name == '404':
            raise ApiException(reason='Not Found')

        my_response = namedtuple('my_response', 'metadata status')
        my_status = namedtuple(
            'my_status', 'desired_number_scheduled number_available '
            'number_ready updated_number_scheduled number_unavailable')

        if self.name == 'test1':
            return my_response(metadata={},
                               status=my_status(desired_number_scheduled=2,
                                                number_available=2,
                                                number_ready=1,
                                                updated_number_scheduled=1,
                                                number_unavailable=1))
        if self.name == 'test2':
            return my_response(metadata={},
                               status=my_status(desired_number_scheduled=2,
                                                number_available=2,
                                                number_ready=2,
                                                updated_number_scheduled=2,
                                                number_unavailable=None))

        return my_response(metadata={'key1': 'value1'},
                           status={'key1': 'value1'})
def test_atomic_creation_of_interactive_session(sample_serial_workflow_in_db):
    """Test atomic creation of interactive sessions.

    All interactive session should be created as well as writing the state
    to DB, either all should be done or nothing.
    """
    mocked_k8s_client = Mock()
    mocked_k8s_client.create_namespaced_deployment = Mock(
        side_effect=ApiException(reason="Error while creating deployment")
    )
    # Raise 404 when deleting Deployment, because it doesn't exist
    mocked_k8s_client.delete_namespaced_deployment = Mock(
        side_effect=ApiException(reason="Not Found")
    )
    with patch.multiple(
        "reana_workflow_controller.k8s",
        current_k8s_appsv1_api_client=mocked_k8s_client,
        current_k8s_networking_api_client=DEFAULT,
        current_k8s_corev1_api_client=DEFAULT,
    ) as mocks:
        try:
            kwrm = KubernetesWorkflowRunManager(sample_serial_workflow_in_db)
            if len(InteractiveSessionType):
                kwrm.start_interactive_session(InteractiveSessionType(0).name)
        except REANAInteractiveSessionError:
            mocks[
                "current_k8s_corev1_api_client"
            ].delete_namespaced_service.assert_called_once()
            mocks[
                "current_k8s_networking_api_client"
            ].delete_namespaced_ingress.assert_called_once()
            mocked_k8s_client.delete_namespaced_deployment.assert_called_once()
            assert not sample_serial_workflow_in_db.sessions.all()
Пример #9
0
 def test_logging_records_failed_deletion_of_ui_components(self):
     # Arrange
     body = {'job_name': 'test-spark-job'}
     kubernetes_response = {'status': 'Success'}
     self.mock_k8s_adapter.delete_namespaced_custom_object.return_value = kubernetes_response
     self.mock_k8s_adapter.delete_options.return_value = {"api_version": "version", "other_values": "values"}
     self.mock_k8s_adapter.delete_namespaced_deployment.side_effect = ApiException('Failed to delete proxy')
     self.mock_k8s_adapter.delete_namespaced_service.side_effect = ApiException('Failed to delete service')
     self.mock_k8s_adapter.delete_namespaced_ingress.side_effect = ApiException('Failed to delete ingress')
     # Act
     response_body, response_code = yield self.send_request(body)
     # Assert
     assert response_code == 200
     self.assertDictEqual(response_body, {
         'status': 'success',
         'data': {
             'message': '"test-spark-job" deleted\nError deleting spark ui for job "test-spark-job", please '
                        'contact an administrator',
         }})
     self.mock_logger.error.assert_any_call('Trying to delete spark ui proxy resulted in exception: '
                                            '(Failed to delete proxy)\nReason: None\n')
     self.mock_logger.error.assert_any_call('Trying to delete spark ui service resulted in exception: '
                                            '(Failed to delete service)\nReason: None\n')
     self.mock_logger.error.assert_any_call('Trying to delete spark ui ingress resulted in exception: '
                                            '(Failed to delete ingress)\nReason: None\n')
Пример #10
0
def main():
    SERVICE_TOKEN_FILENAME = "/var/run/secrets/kubernetes.io/serviceaccount/token"
    SERVICE_CERT_FILENAME = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
    KUBERNETES_HOST = "https://%s:%s" % (os.getenv("KUBERNETES_SERVICE_HOST"),
                                         os.getenv("KUBERNETES_SERVICE_PORT"))

    ## configure
    configuration = client.Configuration()
    configuration.host = KUBERNETES_HOST
    if not os.path.isfile(SERVICE_TOKEN_FILENAME):
        raise ApiException("Service token file does not exists.")
    with open(SERVICE_TOKEN_FILENAME) as f:
        token = f.read()
        if not token:
            raise ApiException("Token file exists but empty.")
        configuration.api_key['authorization'] = "bearer " + token.strip('\n')
    if not os.path.isfile(SERVICE_CERT_FILENAME):
        raise ApiException("Service certification file does not exists.")
    with open(SERVICE_CERT_FILENAME) as f:
        if not f.read():
            raise ApiException("Cert file exists but empty.")
        configuration.ssl_ca_cert = SERVICE_CERT_FILENAME
    client.Configuration.set_default(configuration)

    try:
        ret = client.CoreV1Api().list_namespaced_config_map("rest-project")
        print ret
    except ApiException as e:
        print(
            "Exception when calling CoreV1Api->list_namespaced_config_map: %s\n"
            % e)
Пример #11
0
    def patch(self, name: str, namespace: str, body, **kwargs):
        if namespace not in self._namespaced_items:
            raise ApiException(404, "Not Found")

        if not body:
            raise ValueError

        body.metadata = dict(body.metadata, **{"namespace": namespace})
        body.metadata = V1ObjectMeta(**body.metadata)

        for resource in self._namespaced_items[namespace]:
            if resource.metadata.name == name:
                self._namespaced_items[namespace].remove(resource)
                self._items.remove(resource)
                break
        else:
            raise ApiException(404, "Not Found")

        if hasattr(body, "metadata"):
            resource.metadata = body.metadata

        if hasattr(body, "spec"):
            resource.spec = body.spec

        if hasattr(body, "status"):
            resource.status = body.status

        self._namespaced_items[namespace].add(resource)
        self._items.add(resource)
        return resource
Пример #12
0
 def add_operator_to_cluster(self, operator_name, source=None, target_namespaces=[]):
     """
     Install an operator in a list of targeted namespaces
     :param operator_name: (required | str) The name of the operator to be installed
     :param source: (optional | str) The source of the operator to be installed. This parameter
                    can be in the form of a path to a source YAML or JSON, or it can also be
                    passed as a dictionary. If not specified, the package is assumed to be already
                    be visible throught the operator hub and so the source can be discovered.
     :param target_namespaces: (optional | list) A list of namespace/Projects where want the
                                operator to be enabled in. If left unspecified, the operartor
                                will be installed/enabled throughout the entire cluster.
     """
     if source:
         cs_name, cs_namespace = self._source_processor(source)
         if not self.ohp_obj.watch_package_manifest_present(operator_name):
             err_msg = "A package manifest for {} could not be found".format(operator_name)
             logger.exception(err_msg)
             raise ApiException(err_msg)
     else:
         pkg_obj = self.ohp_obj.get_package_manifest(operator_name)
         if pkg_obj:
             cs_name = pkg_obj.status.catalogSource
             cs_namespace = pkg_obj.metadata.namespace
         else:
             logger.exception(err_msg)
             raise ApiException(err_msg)
     install_mode = self._derive_install_mode_from_target_namespaces(operator_name, target_namespaces)
     og_name, og_namespace = self._create_og(operator_name, install_mode, target_namespaces)
     subscription = self.sub_obj.create_subscription(operator_name, install_mode, og_namespace)
     assert subscription.spec.source == cs_name
     assert subscription.spec.sourceNamespace == cs_namespace
     return True
def test_terminate_nodes():

    mock_client = mock.MagicMock()
    mock_client.core.delete_node.side_effect = [None, ApiException(404), None]

    m1, m2, m3 = mock.Mock(), mock.Mock(), mock.Mock()
    success, errors = terminate_nodes(client=mock_client, nodes=[m1, m2, m3])
    expected_calls = [
        mock.call.core.delete_node(
            node, body=V1DeleteOptions(), propagation_policy="foreground"
        )
        for node in [m1, m2, m3]
    ]

    assert mock_client.mock_calls == expected_calls
    assert success == [m1, m3]
    assert errors[0][0] == m2
    assert isinstance(errors[0][1], ApiException)

    mock_client.reset_mock()

    mock_client.core.delete_node.side_effect = [None, ApiException(404), None]
    success, errors = terminate_nodes(client=mock_client, nodes=[m1, m2, m3])
    expected_calls = [
        mock.call.core.delete_node(
            node, body=V1DeleteOptions(), propagation_policy="foreground"
        )
        for node in [m1, m2, m3]
    ]
    assert mock_client.mock_calls == expected_calls
    assert success == [m1, m3]
    assert errors[0][0] == m2
    assert isinstance(errors[0][1], ApiException)
Пример #14
0
    def read_namespaced_stateful_set(self, name, namespace):
        if self.name == 'fail':
            raise ApiException('Get statefulset fail')
        if self.name == '404':
            raise ApiException(reason='Not Found')

        my_response = namedtuple('my_response', 'metadata status')
        my_status = namedtuple('my_status',
                               'current_replicas current_revision ready_replicas replicas update_revision')

        if self.name == 'test1':
            return my_response(metadata={}, status=my_status(current_replicas=2,
                                                             current_revision='revision-123',
                                                             ready_replicas=1,
                                                             replicas=3,
                                                             update_revision='revision-321'))

        if self.name == 'test2':
            return my_response(metadata={}, status=my_status(current_replicas=3,
                                                             current_revision='revision-123',
                                                             ready_replicas=3,
                                                             replicas=3,
                                                             update_revision='revision-123'))

        return my_response(metadata={'key1': 'value1'}, status={'key1': 'value1'})
Пример #15
0
 def test_edi_undeploy_all_models_by_version(self):
     with EDITestServer() as edi:
         with m_func('kubernetes.client.CoreV1Api.list_namespaced_service', 'demo_abc_models_1_0_and_1_1'), \
              m_func('kubernetes.client.CoreV1Api.read_namespaced_service',
                     [ApiException(404), ApiException(404)]), \
              m_func('kubernetes.client.ExtensionsV1beta1Api.read_namespaced_deployment',
                     ['demo_abc_model_1_0', ApiException(404),
                      'demo_abc_model_1_1', ApiException(404)]), \
              m_func('kubernetes.client.apis.apps_v1beta1_api.AppsV1beta1Api.delete_namespaced_deployment',
                     'last_model_deleted'), \
              m_func('kubernetes.client.CoreV1Api.delete_namespaced_service', 'undeploy_done'), \
              mock.patch('legion.k8s.utils.is_code_run_in_cluster', return_value=None), \
              mock.patch('legion.k8s.utils.build_client', return_value=None), \
              mock.patch('legion.k8s.enclave.Enclave.graphite_service', return_value=None):
             deployments = edi.edi_client.undeploy(model='demo-abc-model', version='*')
             # Test count of returned deployments
             self.assertIsInstance(deployments, list)
             self.assertEqual(len(deployments), 2)
             # Validate deleted models
             # Test model #1 fields
             expected_result = {
                 'image': '127.0.0.1/legion/test-bare-model-api-model-1:0.9.0-20181106123540.560.3b9739a',
                 'model': 'demo-abc-model',
                 'version': '1.0',
                 'scale': 1,
                 'ready_replicas': 1,
                 'status': 'ok',
                 'namespace': 'debug-enclave'
             }
             actual_result = {
                 'image': deployments[0].image,
                 'model': deployments[0].model,
                 'version': deployments[0].version,
                 'scale': deployments[0].scale,
                 'ready_replicas': deployments[0].ready_replicas,
                 'status': deployments[0].status,
                 'namespace': deployments[0].namespace
             }
             self.assertDictEqual(expected_result, actual_result)
             # Test model #2 fields
             expected_result = {
                 'image': '127.0.0.1/legion/test-bare-model-api-model-2:0.9.0-20181106123540.560.3b9739a',
                 'model': 'demo-abc-model',
                 'version': '1.1',
                 'scale': 1,
                 'ready_replicas': 1,
                 'status': 'ok',
                 'namespace': 'debug-enclave'
             }
             actual_result = {
                 'image': deployments[1].image,
                 'model': deployments[1].model,
                 'version': deployments[1].version,
                 'scale': deployments[1].scale,
                 'ready_replicas': deployments[1].ready_replicas,
                 'status': deployments[1].status,
                 'namespace': deployments[1].namespace
             }
             self.assertDictEqual(expected_result, actual_result)
Пример #16
0
    def read(self, name: str, namespace: str, **kwargs):  # noqa
        if namespace not in self._namespaced_items:
            raise ApiException(404, "Not Found")

        for resource in self._namespaced_items[namespace]:
            if resource.metadata.name == name:
                return resource
        else:
            raise ApiException(404, "Not Found")
Пример #17
0
def test_pod_scheduled(init_openshift_deployer, pod_not_deployed):
    od = init_openshift_deployer
    flexmock(od).should_receive("get_pod").and_raise(
        ApiException(status=404, )).and_return(
            V1Pod(status=V1PodStatus(phase="Running"))).and_return(
                V1Pod(status=V1PodStatus(phase="Succeeded")))
    flexmock(od.api).should_receive("create_namespaced_pod").and_raise(
        ApiException(status="403")).and_return(1)
    od.deploy_pod(["false"])
Пример #18
0
    def delete(self, name: str, namespace: str, **kwargs):
        if namespace not in self._namespaced_items.keys():
            raise ApiException(404, "Not Found")

        for service in self._items:
            if service.metadata.name == name:
                self._items.remove(service)
                self._namespaced_items[namespace].remove(service)
                break
        else:
            raise ApiException(404, "Not Found")
Пример #19
0
    def test_start_pod_retries_three_times(self, mock_run_pod_async):
        mock_run_pod_async.side_effect = [
            ApiException(status=409),
            ApiException(status=409),
            ApiException(status=409),
            ApiException(status=409),
        ]
        with pytest.raises(ApiException):
            self.pod_launcher.start_pod(mock.sentinel)

        assert mock_run_pod_async.call_count == 3
Пример #20
0
    def delete_storage_class(self, name, body):
        if self.name == 'fail':
            raise ApiException('Delete storage class fail')
        if self.name == '404' or name == '404':
            raise ApiException(reason='Not Found')

        if self.name == 'test1' or name == 'test1':
            my_response = namedtuple('my_response', 'message')
            return my_response(message='Failed')

        if self.name == 'test2' or name == 'test2':
            my_response = namedtuple('my_response', 'message')
            return my_response(message=None)

        return {'key1': 'value1'}
Пример #21
0
    def create(self, namespace: str, body, **kwargs):
        if not body:
            raise ValueError

        body.metadata = dict(body.metadata, **{"namespace": namespace})
        body.metadata = V1ObjectMeta(**body.metadata)

        if namespace not in self._namespaced_items:
            raise ApiException(404, "Not Found")

        if body in self._namespaced_items[namespace]:
            raise ApiException(409, "AlreadyExists")
        self._items.add(body)
        self._namespaced_items[namespace].add(body)
        return body
Пример #22
0
    def delete_namespaced_deployment(self, name, body, namespace):
        if self.name == 'fail':
            raise ApiException('Delete deployment fail')
        if self.name == '404' or name == '404':
            raise ApiException(reason='Not Found')

        if self.name == 'test1' or name == 'test1':
            my_response = namedtuple('my_response', 'message')
            return my_response(message='Failed')

        if self.name == 'test2' or name == 'test2':
            my_response = namedtuple('my_response', 'message')
            return my_response(message=None)

        return {'key1': 'value1'}
Пример #23
0
def test_is_pod_already_deployed(init_openshift_deployer):
    od = init_openshift_deployer
    flexmock(od).should_receive("get_pod").and_raise(
        ApiException(status=200, reason="POD already exists")
    )
    with pytest.raises(SandcastleExecutionError):
        od.is_pod_already_deployed()
Пример #24
0
def websocket_call(configuration, *args, **kwargs):
    """An internal function to be called in api-client when a websocket
    connection is required. args and kwargs are the parameters of
    apiClient.request method."""

    url = args[1]
    _request_timeout = kwargs.get("_request_timeout", 60)
    _preload_content = kwargs.get("_preload_content", True)
    capture_all = kwargs.get("capture_all", True)
    headers = kwargs.get("headers")

    # Expand command parameter list to indivitual command params
    query_params = []
    for key, value in kwargs.get("query_params", {}):
        if key == 'command' and isinstance(value, list):
            for command in value:
                query_params.append((key, command))
        else:
            query_params.append((key, value))

    if query_params:
        url += '?' + urlencode(query_params)

    try:
        client = WSClient(configuration, get_websocket_url(url), headers, capture_all)
        if not _preload_content:
            return client
        client.run_forever(timeout=_request_timeout)
        return WSResponse('%s' % ''.join(client.read_all()))
    except (Exception, KeyboardInterrupt, SystemExit) as e:
        raise ApiException(status=0, reason=str(e))
Пример #25
0
 def create_namespaced_ingress(namespace, body):
     name = '{}-{}'.format(namespace, body.metadata['name'])
     if name in MockExtensionsV1beta1Api.ingress_map.keys():
         raise ApiException(status=409)
     else:
         MockExtensionsV1beta1Api.ingress_map[name] = body
         return body
Пример #26
0
 def create_namespaced_service(body, namespace):
     name = '{}-{}'.format(body.metadata.name, namespace)
     if name in MockCoreV1Api.service_map.keys():
         raise ApiException(status=409)  # mock conflict
     else:
         MockCoreV1Api.service_map[name] = body
         return body
Пример #27
0
 def read_namespaced_persistent_volume_claim_status(name, **_):
     if name == 'nonexistent-pvc':
         raise ApiException(status=404, reason="nonexistent-pvc")
     elif name == 'pending-pvc':
         return DotDict({'status': DotDict({'phase': 'Pending'})})
     else:
         return DotDict({'status': DotDict({'phase': 'Bound'})})
Пример #28
0
def delete_deployment(source):
    '''
    Deletes the kubernetes deployment defined by name and namespace
    '''
    src_obj = __read_and_render_yaml_file(source)
    metadata = src_obj['metadata']
    name = metadata['name']
    namespace = metadata['namespace']
    body = kubernetes.client.V1DeleteOptions(api_version="v1",
                                             grace_period_seconds=50,
                                             propagation_policy="Background")

    try:
        api_instance = kubernetes.client.AppsV1Api(
            kubernetes.client.ApiClient(configuration))
        api_response = api_instance.delete_namespaced_deployment(
            pretty=pretty, name=name, namespace=namespace, body=body)
        mutable_api_response = api_response.to_dict()

        if mutable_api_response['code'] != 200:
            logging.warning(
                'Reached polling time limit. Deployment is not yet '
                'deleted, but we are backing off. Sorry, but you\'ll '
                'have to check manually.')
        return mutable_api_response
    except (ApiException, HTTPError) as exc:
        if isinstance(exc, ApiException) and exc.status == 404:
            return None
        else:
            logging.exception(
                'Exception when calling '
                'ExtensionsV1beta1Api->delete_namespaced_deployment: '
                '{0}'.format(exc))
            raise ApiException(exc)
Пример #29
0
def test_workflow_finish_and_kubernetes_not_available(
    in_memory_queue_connection,
    sample_serial_workflow_in_db,
    consume_queue,
):
    """Test workflow finish with a Kubernetes connection troubles."""
    sample_serial_workflow_in_db.status = RunStatus.running
    next_status = RunStatus.failed
    job_status_consumer = JobStatusConsumer(
        connection=in_memory_queue_connection)
    workflow_status_publisher = WorkflowStatusPublisher(
        connection=in_memory_queue_connection, queue=job_status_consumer.queue)
    workflow_status_publisher.publish_workflow_status(
        str(sample_serial_workflow_in_db.id_),
        next_status.value,
    )
    k8s_corev1_api_client_mock = Mock()
    k8s_corev1_api_client_mock.delete_namespaced_job = Mock(
        side_effect=ApiException(reason="Could not delete job.", status=404))
    with patch(
            "reana_workflow_controller.consumer.current_k8s_corev1_api_client",
            k8s_corev1_api_client_mock,
    ):
        consume_queue(job_status_consumer, limit=1)
    assert sample_serial_workflow_in_db.status == next_status
Пример #30
0
def portforward_call(configuration, _method, url, **kwargs):
    """An internal function to be called in api-client when a websocket
    connection is required for port forwarding. args and kwargs are the
    parameters of apiClient.request method."""

    query_params = kwargs.get("query_params")

    ports = []
    for param, value in query_params:
        if param == 'ports':
            for port in value.split(','):
                try:
                    port_number = int(port)
                except ValueError:
                    raise ApiValueError("Invalid port number: %s" % port)
                if not (0 < port_number < 65536):
                    raise ApiValueError("Port number must be between 0 and 65536: %s" % port)
                if port_number in ports:
                    raise ApiValueError("Duplicate port numbers: %s" % port)
                ports.append(port_number)
    if not ports:
        raise ApiValueError("Missing required parameter `ports`")

    url = get_websocket_url(url, query_params)
    headers = kwargs.get("headers")

    try:
        websocket = create_websocket(configuration, url, headers)
        return PortForward(websocket, ports)
    except (Exception, KeyboardInterrupt, SystemExit) as e:
        raise ApiException(status=0, reason=str(e))