示例#1
0
def test_get_revision_dict_last_site_action_and_successful_site_action():
    """
    Tests the processing of revision dict response from deckhand
    for last_site_action and successful_site_action revision
    """
    helper = ConfigdocsHelper(CTX)
    helper.deckhand.get_revision_list = lambda: yaml.load("""
---
  - id: 1
    url: https://deckhand/api/v1.0/revisions/1
    createdAt: 2018-04-30T21:23Z
    buckets: [mop]
    tags: [committed, site-action-success]
    validationPolicies:
      site-deploy-validation:
        status: succeeded
  - id: 2
    url: https://deckhand/api/v1.0/revisions/2
    createdAt: 2018-04-30T23:35Z
    buckets: [flop, mop]
    tags: [committed, site-action-failure]
    validationPolicies:
      site-deploy-validation:
        status: succeeded
...
""")
    rev_dict = helper._get_revision_dict()
    successful_site_action = rev_dict.get(
        configdocs_helper.SUCCESSFUL_SITE_ACTION)
    last_site_action = rev_dict.get(configdocs_helper.LAST_SITE_ACTION)
    assert successful_site_action.get('id') == 1
    assert last_site_action.get('id') == 2
示例#2
0
def test__get_revision_dict_errs():
    """
    tests getting a revision dictionary method when the deckhand
    client has raised an exception
    """

    def _raise_dre():
        raise DeckhandResponseError(
            status_code=9000, response_message='This is bogus')

    def _raise_nree():
        raise NoRevisionsExistError()

    helper = ConfigdocsHelper(CTX)
    helper.deckhand.get_revision_list = _raise_dre

    with pytest.raises(AppError):
        helper._get_revision_dict()

    helper.deckhand.get_revision_list = _raise_nree
    rev_dict = helper._get_revision_dict()
    committed = rev_dict.get(configdocs_helper.COMMITTED)
    buffer = rev_dict.get(configdocs_helper.BUFFER)
    latest = rev_dict.get(configdocs_helper.LATEST)
    count = rev_dict.get(configdocs_helper.REVISION_COUNT)
    assert committed is None
    assert buffer is None
    assert latest is None
    assert count == 0
示例#3
0
def test_get_collection_docs():
    """
    Returns the representation of the yaml docs from deckhand
    """
    helper = ConfigdocsHelper(CTX)
    helper.deckhand.get_docs_from_revision = (
        lambda revision_id, bucket_id: "{'yaml': 'yaml'}")
    helper._get_revision_dict = lambda: REV_EMPTY_DICT
    helper.deckhand.get_diff = (
        lambda old_revision_id, new_revision_id: DIFF_EMPTY_DICT)

    with pytest.raises(ApiError):
        helper.get_collection_docs(configdocs_helper.BUFFER, 'mop')

    with pytest.raises(ApiError):
        helper.get_collection_docs(configdocs_helper.COMMITTED, 'mop')

    helper._get_revision_dict = lambda: REV_COMMIT_AND_BUFFER_DICT
    helper.deckhand.get_diff = (
        lambda old_revision_id, new_revision_id: DIFF_COMMIT_AND_BUFFER_DICT)
    yaml_str = helper.get_collection_docs(configdocs_helper.BUFFER, 'mop')
    assert len(yaml_str) == 16

    yaml_str = helper.get_collection_docs(configdocs_helper.COMMITTED, 'mop')
    assert len(yaml_str) == 16
示例#4
0
    def test_post_collection(self):
        """
        Tests the post collection method of the ConfigdocsResource
        """
        helper = None
        collection_id = 'trees'
        document_data = 'lots of info'
        with patch.object(ConfigdocsHelper, 'add_collection') as mock_method:
            cdr = ConfigDocsResource()
            helper = ConfigdocsHelper(CTX)
            helper.is_buffer_valid_for_bucket = lambda a, b: True
            helper.get_deckhand_validation_status = (
                lambda a: ConfigdocsHelper._format_validations_to_status([], 0)
            )
            cdr.post_collection(helper=helper,
                                collection_id=collection_id,
                                document_data=document_data)

        mock_method.assert_called_once_with(collection_id, document_data)

        with pytest.raises(ApiError):
            cdr = ConfigDocsResource()
            helper = ConfigdocsHelper(CTX)
            # not valid for bucket
            helper.is_buffer_valid_for_bucket = lambda a, b: False
            helper.get_deckhand_validation_status = (
                lambda a: ConfigdocsHelper._format_validations_to_status([], 0)
            )
            cdr.post_collection(helper=helper,
                                collection_id=collection_id,
                                document_data=document_data)
示例#5
0
def test__get_revision_dict_commit_and_buff():
    """
    Tests the processing of revision dict response from dechand
    with a committed and a buffer revision
    """
    helper = ConfigdocsHelper(CTX)
    helper.deckhand.get_revision_list = lambda: yaml.load("""
---
  - id: 1
    url: https://deckhand/api/v1.0/revisions/1
    createdAt: 2017-07-14T21:23Z
    buckets: [mop]
    tags: [a, b, committed]
    validationPolicies:
      site-deploy-validation:
        status: failed
  - id: 2
    url: https://deckhand/api/v1.0/revisions/2
    createdAt: 2017-07-16T01:15Z
    buckets: [flop, mop]
    tags: [b]
    validationPolicies:
      site-deploy-validation:
        status: succeeded
...
""")
    rev_dict = helper._get_revision_dict()
    committed = rev_dict.get(configdocs_helper.COMMITTED)
    buffer = rev_dict.get(configdocs_helper.BUFFER)
    latest = rev_dict.get(configdocs_helper.LATEST)
    count = rev_dict.get(configdocs_helper.REVISION_COUNT)
    assert committed.get('id') == 1
    assert buffer.get('id') == 2
    assert latest.get('id') == 2
    assert count == 2
示例#6
0
def test__get_deckhand_validation_errors_empty_results():
    """
    Tets the functionality of processing a response from deckhand
    """
    helper = ConfigdocsHelper(CTX)
    helper.deckhand._get_base_validation_resp = (
        lambda revision_id: FK_VAL_BASE_RESP_EMPTY)
    assert len(helper._get_deckhand_validation_errors(5)) == 0
示例#7
0
    def create_action(self, action, context, allow_intermediate_commits=False):
        # use uuid assigned for this request as the id of the action.
        action['id'] = ulid.ulid()
        # the invoking user
        action['user'] = context.user
        # add current timestamp (UTC) to the action.
        action['timestamp'] = str(datetime.utcnow())
        # validate that action is supported.
        LOG.info("Attempting action: %s", action['name'])
        if action['name'] not in SUPPORTED_ACTION_MAPPINGS:
            raise ApiError(title='Unable to start action',
                           description='Unsupported Action: {}'.format(
                               action['name']))

        dag = SUPPORTED_ACTION_MAPPINGS.get(action['name'])['dag']
        action['dag_id'] = dag

        # Set up configdocs_helper
        self.configdocs_helper = ConfigdocsHelper(context)

        # Retrieve last committed design revision
        action['committed_rev_id'] = self.get_committed_design_version()

        # Check for intermediate commit
        self.check_intermediate_commit_revision(allow_intermediate_commits)

        # populate action parameters if they are not set
        if 'parameters' not in action:
            action['parameters'] = {}
        # validate if there is any validation to do
        validator = SUPPORTED_ACTION_MAPPINGS.get(action['name'])['validator']
        if validator is not None:
            # validators will raise ApiError if they are not validated.
            validator(action)

        # invoke airflow, get the dag's date
        dag_execution_date = self.invoke_airflow_dag(dag_id=dag,
                                                     action=action,
                                                     context=context)
        # set values on the action
        action['dag_execution_date'] = dag_execution_date
        action['dag_status'] = 'SCHEDULED'

        # context_marker is the uuid from the request context
        action['context_marker'] = context.request_id

        # insert the action into the shipyard db
        self.insert_action(action=action)
        self.audit_control_command_db({
            'id': ulid.ulid(),
            'action_id': action['id'],
            'command': 'invoke',
            'user': context.user
        })

        return action
示例#8
0
def test_tag_buffer():
    """
    Tests that the tag buffer method attempts to tag the right version
    """
    with patch.object(ConfigdocsHelper, 'tag_revision') as mock_method:
        helper = ConfigdocsHelper(CTX)
        helper._get_revision_dict = lambda: REV_BUFFER_DICT
        helper.tag_buffer('artful')

    mock_method.assert_called_once_with(5, 'artful')
示例#9
0
    def test_commit_configdocs_buffer_err(self):
        """
        Tests the CommitConfigDocsResource method commit_configdocs
        """
        ccdr = CommitConfigDocsResource()

        with pytest.raises(ApiError):
            helper = ConfigdocsHelper(CTX)
            helper.is_buffer_empty = lambda: True
            helper.get_validations_for_buffer = lambda: {'status': 'Success'}
            ccdr.commit_configdocs(helper, False, False)
示例#10
0
def test_get_validations_for_revision(p1, p2, p3):
    """
    Tests the functionality of the get_validations_for_revision method
    """
    helper = ConfigdocsHelper(CTX)
    helper._get_deckhand_validation_errors = lambda revision_id: []
    val_status = helper.get_validations_for_revision(3)
    err_count = val_status['details']['errorCount']
    err_list_count = len(val_status['details']['messageList'])
    assert err_list_count == 6
    assert val_status['details']['errorCount'] == 4
示例#11
0
def test_add_collection():
    """
    Tests the adding of a collection to deckhand - primarily
    error handling
    """
    with patch.object(DeckhandClient, 'put_bucket') as mock_method:
        helper = ConfigdocsHelper(CTX)
        helper._get_revision_dict = lambda: REV_BUFFER_DICT
        assert helper.add_collection('mop', 'yaml:yaml') == 5

    mock_method.assert_called_once_with('mop', 'yaml:yaml')
示例#12
0
def test__get_deckhand_validations_empty_errors():
    """
    Tets the functionality of processing a response from deckhand
    """
    helper = ConfigdocsHelper(CTX)
    helper.deckhand._get_base_validation_resp = (
        lambda revision_id: FK_VAL_BASE_RESP)
    helper.deckhand._get_subset_validation_response = (
        lambda reivsion_id, subset_name: FK_VAL_SUBSET_RESP)
    helper.deckhand._get_entry_validation_response = (
        lambda reivsion_id, subset_name, entry_id: FK_VAL_ENTRY_RESP_EMPTY)
    assert len(helper._get_deckhand_validation_errors(5)) == 0
示例#13
0
def test_get_validations_for_revision_dh_render(get_endpoint):
    """
    Tests the functionality of the get_validations_for_revision method
    """
    helper = ConfigdocsHelper(CTX)
    hold_ve = helper.__class__._get_validation_endpoints
    helper._get_deckhand_validation_errors = lambda revision_id: []
    val_status = helper.get_validations_for_revision(3)
    err_count = val_status['details']['errorCount']
    err_list_count = len(val_status['details']['messageList'])
    assert err_count == err_list_count
    assert val_status['details']['errorCount'] == 1
    assert val_status['details']['messageList'][0]['message'] == 'broken!'
示例#14
0
    def test_commit_configdocs(self):
        """
        Tests the CommitConfigDocsResource method commit_configdocs
        """
        ccdr = CommitConfigDocsResource()
        commit_resp = None
        with patch.object(ConfigdocsHelper, 'tag_buffer') as mock_method:
            helper = ConfigdocsHelper(CTX)
            helper.is_buffer_empty = lambda: False
            helper.get_validations_for_buffer = lambda: {'status': 'Success'}
            commit_resp = ccdr.commit_configdocs(helper, False, False)

        mock_method.assert_called_once_with('committed')
        assert commit_resp['status'] == 'Success'

        commit_resp = None
        with patch.object(ConfigdocsHelper, 'tag_buffer') as mock_method:
            helper = ConfigdocsHelper(CTX)
            helper.is_buffer_empty = lambda: False
            helper.get_validations_for_buffer = (
                lambda: {
                    'status': 'Failure',
                    'code': '400 Bad Request',
                    'message': 'this is a mock response'
                })
            commit_resp = ccdr.commit_configdocs(helper, False, False)
        assert '400' in commit_resp['code']
        assert commit_resp['message'] is not None
        assert commit_resp['status'] == 'Failure'
示例#15
0
    def test_commit_configdocs_dryrun(self):
        """
        Tests the CommitConfigDocsResource method commit_configdocs
        """
        ccdr = CommitConfigDocsResource()
        commit_resp = None
        with patch.object(ConfigdocsHelper, 'tag_buffer') as mock_method:
            helper = ConfigdocsHelper(CTX)
            helper.is_buffer_empty = lambda: False
            helper.get_validations_for_buffer = lambda: {'status': 'Success'}
            commit_resp = ccdr.commit_configdocs(helper, False, True)

        assert '200' in commit_resp['code']
        assert commit_resp['message'] == 'DRYRUN'
        assert commit_resp['status'] == 'Success'
示例#16
0
    def test_commit_configdocs_force(self):
        """
        Tests the CommitConfigDocsResource method commit_configdocs
        """
        ccdr = CommitConfigDocsResource()
        commit_resp = None
        with patch.object(ConfigdocsHelper, 'tag_buffer') as mock_method:
            helper = ConfigdocsHelper(CTX)
            helper.is_buffer_empty = lambda: False
            helper.get_validations_for_buffer = lambda: {'status': 'Failure'}
            commit_resp = ccdr.commit_configdocs(helper, True, False)

        mock_method.assert_called_once_with('committed')
        assert '200' in commit_resp['code']
        assert 'FORCED' in commit_resp['message']
        assert commit_resp['status'] == 'Failure'
示例#17
0
    def on_post(self, req, resp, collection_id):
        """
        Ingests a collection of documents
        """
        content_length = req.content_length or 0
        if (content_length == 0):
            raise ApiError(
                title=('Content-Length is a required header'),
                description='Content Length is 0 or not specified',
                status=falcon.HTTP_400,
                error_list=[{
                    'message': (
                        'The Content-Length specified is 0 or not set. Check '
                        'that a valid payload is included with this request '
                        'and that your client is properly including a '
                        'Content-Length header. Note that a newline character '
                        'in a prior header can trigger subsequent headers to '
                        'be ignored and trigger this failure.')
                }],
                retry=False, )
        document_data = req.stream.read(content_length)

        buffer_mode = req.get_param('buffermode')

        helper = ConfigdocsHelper(req.context)
        validations = self.post_collection(
            helper=helper,
            collection_id=collection_id,
            document_data=document_data,
            buffer_mode_param=buffer_mode)

        resp.location = '/api/v1.0/configdocs/{}'.format(collection_id)
        resp.body = self.to_json(validations)
        resp.status = falcon.HTTP_201
示例#18
0
def test_generate_dh_val_message():
    """Test for static method to generate a ValidationMessage

    Test for something that is already a validation message.
    """
    message = {
        'validation_schema': 'vs',
        'schema_path': 'sp',
        'name': 'dn',
        'schema': 's',
        'path': 'p',
        'error_section': 'es',
        'message': 'm'
    }
    expected = {
        'message': 'm',
        'error': True,
        'kind': 'ValidationMessage',
        'level': 'Error',
        'source': 'Deckhand',
        'name': 'dn',
        'documents': [{'name': 'dn', 'schema': 's'}],
        'diagnostic': 'Section: es at p (schema vs at sp)',
    }

    generated = ConfigdocsHelper._generate_dh_val_msg(
        message,
        dh_result_name='x'
    )
    assert generated == expected
示例#19
0
def test_generate_validation_message_args_full():
    """Test for static method to generate a ValidationMessage

    Test for something that is already a validation message.
    """
    message = {
        'message': 'message',
        'error': False,
        'kind': 'ValidationMessage',
        'level': 'Warning',
        'source': 'testing',
        'name': 'namename',
        'documents': []
    }
    kwargs = {
        'message': 'not this',
        'error': True
    }
    expected = {
        'message': 'message',
        'error': False,
        'kind': 'ValidationMessage',
        'level': 'Warning',
        'source': 'testing',
        'name': 'namename',
        'documents': [],
        'diagnostic': None
    }

    generated = ConfigdocsHelper._generate_validation_message(message,
                                                              **kwargs)
    assert generated == expected
示例#20
0
def test_generate_validation_message_args():
    """Test for static method to generate a ValidationMessage

    Test for a SimpleMessage message with some arg defaults
    """
    message = {
        'message': 'message',
        'error': True,
        'kind': 'SimpleMessage'
    }
    kwargs = {
        'name': 'namename',
        'source': 'testing',
        'message': 'not this',
        'error': False,
        'documents': []
    }
    expected = {
        'message': 'message',
        'error': True,
        'kind': 'ValidationMessage',
        'level': 'Error',
        'source': 'testing',
        'name': 'namename',
        'documents': [],
        'diagnostic': None
    }

    generated = ConfigdocsHelper._generate_validation_message(message,
                                                              **kwargs)
    assert generated == expected
示例#21
0
    def post_collection(self,
                        helper,
                        collection_id,
                        document_data,
                        buffer_mode_param=None):
        """
        Ingest the collection after checking preconditions
        """
        if buffer_mode_param is None:
            buffer_mode = BufferMode.REJECTONCONTENTS
        else:
            buffer_mode = ConfigdocsHelper.get_buffer_mode(buffer_mode_param)

        if helper.is_buffer_valid_for_bucket(collection_id, buffer_mode):
            buffer_revision = helper.add_collection(collection_id,
                                                    document_data)
            return helper.get_deckhand_validation_status(buffer_revision)
        else:
            raise ApiError(
                title='Invalid collection specified for buffer',
                description='Buffermode : {}'.format(buffer_mode.value),
                status=falcon.HTTP_409,
                error_list=[{
                    'message': ('Buffer is either not empty or the '
                                'collection already exists in buffer. '
                                'Setting a different buffermode may '
                                'provide the desired functionality')
                }],
                retry=False,
            )
示例#22
0
def test_construct_configdocs_helper():
    """
    Creates a configdoc helper, tests that the context
    is passed to the sub-helper
    """
    helper = ConfigdocsHelper(CTX)
    assert helper.ctx == CTX
示例#23
0
def test__get_revision_dict_empty():
    """
    Tests the processing of revision dict response from dechand
    where the response is an empty list
    """
    helper = ConfigdocsHelper(CTX)
    helper.deckhand.get_revision_list = lambda: []
    rev_dict = helper._get_revision_dict()
    committed = rev_dict.get(configdocs_helper.COMMITTED)
    buffer = rev_dict.get(configdocs_helper.BUFFER)
    latest = rev_dict.get(configdocs_helper.LATEST)
    count = rev_dict.get(configdocs_helper.REVISION_COUNT)
    assert committed is None
    assert buffer is None
    assert latest is None
    assert count == 0
示例#24
0
def test_is_buffer_emtpy():
    """
    Test the method to check if the configdocs buffer is empty
    """
    helper = ConfigdocsHelper(CTX)
    helper._get_revision_dict = lambda: REV_BUFFER_DICT
    assert not helper.is_buffer_empty()

    helper._get_revision_dict = lambda: REV_BUFF_EMPTY_DICT
    assert helper.is_buffer_empty()

    helper._get_revision_dict = lambda: REV_NO_COMMIT_DICT
    assert not helper.is_buffer_empty()

    helper._get_revision_dict = lambda: REV_EMPTY_DICT
    assert helper.is_buffer_empty()
示例#25
0
 def test_post_collection_not_valid_for_buffer(self):
     """
     Tests the post collection method of the ConfigdocsResource
     """
     helper = None
     collection_id = 'trees'
     document_data = 'lots of info'
     with pytest.raises(ApiError) as apie:
         cdr = ConfigDocsResource()
         helper = ConfigdocsHelper(CTX)
         # not valid for bucket
         helper.get_deckhand_validation_status = (
             lambda a: ConfigdocsHelper._format_validations_to_status([], 0)
         )
         cdr.post_collection(helper=helper,
                             collection_id=collection_id,
                             document_data=document_data)
     assert apie.value.status == '409 Conflict'
示例#26
0
    def test_get_collection(self):
        helper = None
        with patch.object(ConfigdocsHelper,
                          'get_collection_docs') as mock_method:
            cdr = ConfigDocsResource()
            helper = ConfigdocsHelper(CTX)
            cdr.get_collection(helper, 'apples')

        mock_method.assert_called_once_with('buffer', 'apples')
示例#27
0
 def on_get(self, req, resp):
     """
     Returns the whole set of rendered documents
     """
     version = (req.params.get('version') or 'buffer')
     self._validate_version_parameter(version)
     helper = ConfigdocsHelper(req.context)
     resp.body = self.get_rendered_configdocs(helper=helper,
                                              version=version)
     resp.append_header('Content-Type', 'application/x-yaml')
     resp.status = falcon.HTTP_200
示例#28
0
    def test_post_collection_not_added(self):
        """
        Tests the post collection method of the ConfigdocsResource
        """
        helper = None
        collection_id = 'trees'
        document_data = 'lots of info'
        with patch.object(ConfigdocsHelper, 'add_collection') as mock_method:
            cdr = ConfigDocsResource()
            helper = ConfigdocsHelper(CTX)
            helper.get_deckhand_validation_status = (
                lambda a: ConfigdocsHelper._format_validations_to_status([], 0)
            )
            with pytest.raises(ApiError) as apie:
                cdr.post_collection(helper=helper,
                                    collection_id=collection_id,
                                    document_data=document_data)

            assert apie.value.status == '400 Bad Request'
        mock_method.assert_called_once_with(collection_id, document_data)
示例#29
0
 def on_get(self, req, resp, collection_id):
     """
     Returns a collection of documents
     """
     version = (req.params.get('version') or 'buffer')
     self._validate_version_parameter(version)
     helper = ConfigdocsHelper(req.context)
     # Not reformatting to JSON or YAML since just passing through
     resp.body = self.get_collection(
         helper=helper, collection_id=collection_id, version=version)
     resp.append_header('Content-Type', 'application/x-yaml')
     resp.status = falcon.HTTP_200
示例#30
0
 def on_post(self, req, resp):
     """
     Get validations from all UCP components
     Functionality does not exist yet
     """
     # force and dryrun query parameter is False unless explicitly true
     force = req.get_param_as_bool(name='force') or False
     dryrun = req.get_param_as_bool(name='dryrun') or False
     helper = ConfigdocsHelper(req.context)
     validations = self.commit_configdocs(helper, force, dryrun)
     resp.body = self.to_json(validations)
     resp.status = validations.get('code', falcon.HTTP_200)