Exports bundle to ckan instance.

    Args:
        bundle (ambry.bundle.Bundle):
        force (bool, optional): if True, ignore existance error and continue to export.
        force_restricted (bool, optional): if True, then export restricted bundles as private (for debugging
            purposes).

    Raises:
        EnvironmentError: if ckan credentials are missing or invalid.
        UnpublishedAccessError: if dataset has unpublished access - one from ('internal', 'test',
            'controlled', 'restricted', 'census').

def export(bundle, force=False, force_restricted=False):
    """ Exports bundle to ckan instance.

    Args:
        bundle (ambry.bundle.Bundle):
        force (bool, optional): if True, ignore existance error and continue to export.
        force_restricted (bool, optional): if True, then export restricted bundles as private (for debugging
            purposes).

    Raises:
        EnvironmentError: if ckan credentials are missing or invalid.
        UnpublishedAccessError: if dataset has unpublished access - one from ('internal', 'test',
            'controlled', 'restricted', 'census').

    """
    if not ckan:
        raise EnvironmentError(MISSING_CREDENTIALS_MSG)

    # publish dataset.
    try:
        ckan.action.package_create(**_convert_bundle(bundle))
    except ckanapi.ValidationError:
        if force:
            logger.warning(
                '{} dataset already exported, but new export forced. Continue to export dataset stuff.'
                .format(bundle.dataset))
        else:
            raise

    # set permissions.
    access = bundle.dataset.config.metadata.about.access

    if access == 'restricted' and force_restricted:
        access = 'private'

    assert access, 'CKAN publishing requires access level.'

    if access in ('internal',  'controlled', 'restricted', 'census'):
        # Never publish dataset with such access.
        raise UnpublishedAccessError(
            '{} dataset can not be published because of {} access.'
            .format(bundle.dataset.vid, bundle.dataset.config.metadata.about.access))
    elif access == 'public':
        # The default permission of the CKAN allows to edit and create dataset without logging in. But
        # admin of the certain CKAN instance can change default permissions.
        # http://docs.ckan.org/en/ckan-1.7/authorization.html#anonymous-edit-mode
        user_roles = [
            {'user': 'visitor', 'domain_object': bundle.dataset.vid.lower(), 'roles': ['editor']},
            {'user': 'logged_in', 'domain_object': bundle.dataset.vid.lower(), 'roles': ['editor']},
        ]

    elif access == 'registered':
        # Anonymous has no access, logged in users can read/edit.
        # http://docs.ckan.org/en/ckan-1.7/authorization.html#logged-in-edit-mode
        user_roles = [
            {'user': 'visitor', 'domain_object': bundle.dataset.vid.lower(), 'roles': []},
            {'user': 'logged_in', 'domain_object': bundle.dataset.vid.lower(), 'roles': ['editor']}
        ]
    elif access in ('private', 'licensed', 'test'):
        # Organization users can read/edit
        # http://docs.ckan.org/en/ckan-1.7/authorization.html#publisher-mode
        # disable access for anonymous and logged_in
        user_roles = [
            {'user': 'visitor', 'domain_object': bundle.dataset.vid.lower(), 'roles': []},
            {'user': 'logged_in', 'domain_object': bundle.dataset.vid.lower(), 'roles': []}
        ]
        organization_users = ckan.action.organization_show(id=CKAN_CONFIG.organization)['users']
        for user in organization_users:
            user_roles.append({
                'user': user['id'], 'domain_object': bundle.dataset.vid.lower(), 'roles': ['editor']}),

    for role in user_roles:
        # http://docs.ckan.org/en/ckan-2.4.1/api/#ckan.logic.action.update.user_role_update
        ckan.action.user_role_update(**role)

    # TODO: Using bulk update gives http500 error. Try later with new version.
    # http://docs.ckan.org/en/ckan-2.4.1/api/#ckan.logic.action.update.user_role_bulk_update - the same
    # ckan.action.user_role_bulk_update(user_roles=user_roles)

    # publish partitions
    for partition in bundle.partitions:
        ckan.action.resource_create(**_convert_partition(partition))

    # publish schema.csv
    ckan.action.resource_create(**_convert_schema(bundle))

    # publish external documentation
    for name, external in six.iteritems(bundle.dataset.config.metadata.external_documentation):
        ckan.action.resource_create(**_convert_external(bundle, name, external))