def is_pks_enabled():
    from container_service_extension.server.service import Service
    return Service().is_pks_enabled()
def get_pks_cache():
    from container_service_extension.server.service import Service
    return Service().get_pks_cache()
def get_registered_def_interface() -> common_models.DefInterface:
    """Fetch the native cluster interface loaded during server startup."""
    from container_service_extension.server.service import Service
    return Service().get_kubernetes_interface()
def get_registered_def_entity_type() -> common_models.DefEntityType:
    """Fetch the native cluster entity type loaded during server startup."""
    from container_service_extension.server.service import Service
    return Service().get_native_cluster_entity_type()
def process_request(message):
    """
    Determine the correct api handler to invoke and invoke it.

    The request URI, api version and HTTP verb are used to determine the
    request operation and the corresponding handler.

    Additionaly support for payload verification, query param verification
    will be added in a later point of time.

    URL template matching is also performed to compute values of url template
    parameters. These computed values, request body and query params are all
    sent to handlers in form of a dictionary.

    :param dict message: message recived over AMQP/MQTT bus representing the
        incoming REST request.

    :returns: response computed by the handler after processing the request
    """
    LOGGER.debug(f"Incoming request message: {json.dumps(message)}")

    api_version_header = _parse_accept_header(
        accept_header=message['headers'].get('Accept'))
    api_version = _get_api_version_from_accept_header(
        api_version_header=api_version_header)

    # Convert to upper case for matching the ENUM values
    method = RequestMethod(message['method'].upper())
    url = message['requestUri']
    url_tokens = url.split("/")
    # ignore the vcd host and /api in the url
    if len(url_tokens) > 2:
        url_tokens = url_tokens[2:]

    query_params = None
    if message['queryString']:
        query_params = dict(parse_qsl(message['queryString']))

    request_body = None
    # Should we do a content-type check? and allow only application/json content?  # noqa: E501
    if len(message['body']) > 0:
        raw_body = base64.b64decode(message['body']).decode(
            sys.getfilesystemencoding())  # noqa: E501
        request_body = json.loads(raw_body)

    found = False
    url_data = {}
    for entry in CSE_REQUEST_DISPATCHER_LIST:
        if found:
            break
        if len(entry['url_tokens']) != len(url_tokens):
            continue

        url_matched = True
        for i in range(0, len(url_tokens)):
            token = entry['url_tokens'][i]
            if token.startswith("$"):
                url_data[token[1:]] = url_tokens[i]
            elif token.lower() != url_tokens[i].lower():
                url_matched = False
                url_data.clear()
                break

        if not url_matched:
            continue

        if method not in entry.keys():
            raise cse_exception.MethodNotAllowedRequestError()

        handlers = entry[method]
        matched_handler = None
        supported_api_versions = []
        for versions in handlers.keys():
            supported_api_versions.extend(list(versions))
            if api_version in versions or '*' in versions:
                matched_handler = handlers[versions]
                break

        if not matched_handler:
            raise cse_exception.NotAcceptableRequestError(
                error_message="Invalid api version specified. Expected "
                f"api version '{supported_api_versions}'.")

        operation = matched_handler['operation']
        handler_method = matched_handler['handler']

        # ToDo: Extra validation based on allowed query params, content type etc.  # noqa: E501
        found = True

    if not found:
        raise cse_exception.NotFoundRequestError()

    # /system operations are excluded from these checks
    if operation not in (CseOperation.SYSTEM_INFO, CseOperation.SYSTEM_UPDATE):
        from container_service_extension.server.service import Service
        if not Service().is_running():
            raise cse_exception.BadRequestError(
                error_message='CSE service is disabled. '
                'Contact the System Administrator.')

    # create request data dict from incoming message data
    request_data = {'url': url}

    # ToDo: Device better way to send request body to handlers.
    if request_body:
        # update request_data with request_body
        LOGGER.debug(f"request body: {request_data}")

    # update request data dict with query params data
    # ToDo: Device better way to send request query params to handlers.
    if query_params:
        # update request_data with query_params
        LOGGER.debug(f"query parameters: {query_params}")

    # update request spec with operation specific data in the url
    request_data.update(url_data)

    # remove None values from request payload
    data = {k: v for k, v in request_data.items() if v is not None}

    # extract out the authorization token
    tenant_auth_token = message['headers'].get('x-vcloud-authorization')
    is_jwt_token = False
    auth_header = message['headers'].get('Authorization')
    if auth_header:
        tokens = auth_header.split(" ")
        if len(tokens) == 2 and tokens[0].lower() == 'bearer':
            tenant_auth_token = tokens[1]
            is_jwt_token = True

    # create operation context
    operation_ctx = ctx.OperationContext(tenant_auth_token,
                                         is_jwt=is_jwt_token,
                                         request_id=message['id'])

    try:
        body_content = handler_method(data, operation_ctx)
    finally:
        if not operation_ctx.is_async:
            operation_ctx.end()

    if not isinstance(body_content, (list, dict)):
        body_content = \
            {shared_constants.RESPONSE_MESSAGE_KEY: str(body_content)}
    response = {
        'status_code': operation.ideal_response_code,
        'body': body_content,
    }
    LOGGER.debug(f"Outgoing response: {str(response)}")
    return response
def process_request(message):
    from container_service_extension.server.service import Service
    LOGGER.debug(f"Incoming request message: {json.dumps(message)}")

    api_version_header = _parse_accept_header(
        accept_header=message['headers'].get('Accept'))
    api_version = _get_api_version_from_accept_header(
        api_version_header=api_version_header)
    url_data = _get_url_data(method=message['method'],
                             url=message['requestUri'],
                             api_version=api_version)  # noqa: E501
    operation = url_data[_OPERATION_KEY]

    # Check api version and if server is disabled or not
    # /system operations are excluded from these checks
    if operation not in (CseOperation.SYSTEM_INFO, CseOperation.SYSTEM_UPDATE):
        if not Service().is_running():
            raise cse_exception.BadRequestError(
                error_message='CSE service is disabled. '
                'Contact the System Administrator.')
        else:
            server_api_version = server_utils.get_server_api_version()
            if api_version != server_api_version:
                raise cse_exception.NotAcceptableRequestError(
                    error_message="Invalid api version specified. Expected "
                    f"api version '{server_api_version}'.")

    # create request data dict from incoming message data
    request_data = {}
    is_cse_3_0_request = _is_cse_3_0_endpoint(message['requestUri'])
    if len(message['body']) > 0:
        raw_body = base64.b64decode(message['body']).decode(
            sys.getfilesystemencoding())  # noqa: E501
        request_body = json.loads(raw_body)
        if is_cse_3_0_request:
            request_data[shared_constants.RequestKey.INPUT_SPEC] = request_body
        else:
            request_data.update(request_body)
        LOGGER.debug(f"request body: {request_data}")
    # update request data dict with query params data
    if message['queryString']:
        query_params = dict(parse_qsl(message['queryString']))
        if is_cse_3_0_request:
            request_data[shared_constants.RequestKey.V35_QUERY] = query_params
        else:
            request_data.update(query_params)
        LOGGER.debug(f"query parameters: {query_params}")
    # update request spec with operation specific data in the url
    request_data.update(url_data)
    # remove None values from request payload
    data = {k: v for k, v in request_data.items() if v is not None}
    # extract out the authorization token
    tenant_auth_token = message['headers'].get('x-vcloud-authorization')
    is_jwt_token = False
    auth_header = message['headers'].get('Authorization')
    if auth_header:
        tokens = auth_header.split(" ")
        if len(tokens) == 2 and tokens[0].lower() == 'bearer':
            tenant_auth_token = tokens[1]
            is_jwt_token = True

    # create operation context
    operation_ctx = ctx.OperationContext(tenant_auth_token,
                                         is_jwt=is_jwt_token,
                                         request_id=message['id'])

    try:
        body_content = OPERATION_TO_HANDLER[operation](data, operation_ctx)
    finally:
        if not operation_ctx.is_async:
            operation_ctx.end()

    if not isinstance(body_content, (list, dict)):
        body_content = \
            {shared_constants.RESPONSE_MESSAGE_KEY: str(body_content)}
    response = {
        'status_code': operation.ideal_response_code,
        'body': body_content,
    }
    LOGGER.debug(f"Outgoing response: {str(response)}")
    return response