hue二次开发记录

758 阅读3分钟

背景介绍

公司要求打通大数据各个服务的用户管理,包含有自主开发的数据治理平台、公司管理的员工用户管理系统、大数据各组件的用户。做到一站式新建、删除、更改等灵活管理。我负责改造hue的用户、角色、权限管理。Hue是一个开源的Apache Hadoop UI系统,可供用户进行数据查询等功能。

本人之前未接触过python,本次开发之前也没抱多大期望,但是通过1个月的学习摸索,终于上线,也算有了个好结果。我记录一下开发期间疑难问题,总结本次开发经验,也希望能帮到大家。

开发过程

1. hue项目编译

1.1 编译环境

意识到hue只支持在linux下编译,我准备了ubantu 22.04虚拟机,切换镜像源这里不赘述。

虚拟机自带python3.10,经实验不能编译(未找到原因),重新安装python3.8(不要卸载python3.10,不然会造成ubantu系统崩溃)。

#安装python3.8
sudo apt install python3.8 python3.8-dev python3.8-distutils python3.8-venv

#安装pip3.8
wget -O /tmp/get-pip.py https://bootstrap.pypa.io/get-pip.py
python3.8 /tmp/get-pip.py

#安装hue依赖
sudo apt-get update -y && apt-get install -y   python3-pip   libkrb5-dev    libsasl2-modules-gssapi-mit   libsasl2-dev   libkrb5-dev   krb5-config   krb5-user   libxml2-dev   libxslt-dev   libmysqlclient-dev   libldap2-dev   libsnappy-dev   python3.8-venv   python3.8-dev   python3.8-distutils   rsync   curl   sudo   git

#安装Django
pip3.8 install django

#编译hue
export PYTHON_VER=python3.8 
export ROOT=/home/wjr/workpace/hue #hue 根目录
cd /home/wjr/workpace/hue #hue 根目录
make apps #编译

以上脚本大概率会成功编译完成,失败也是小问题。

2.代码改造

2.1 新建模块

Hue使用virtualenv隔离和管理python依赖包。为了不污染hue源码,我决定新建一个app模块。

./build/env/bin/hue create_desktop_app appName
./build/env/bin/python tools/app_reg/app_reg.py --install appName

在新建的app编写自己的代码逻辑与api接口

2.2 为其他服务提供api接口

管理api的url路径是否需要Authentication检验的py文件在desktop/core/src/desktop/middleware.py,在 class LoginAndPermissionMiddleware 下process_view方法中有白名单。返回None,即可表示毋须校验。

 if request.path in ['/xxx/xxx/','/xxx/xxxx/']:
      return None
      

3. CICD

在hue源码中找到了DockerFile,文件路径:tools/docker/hue/DcokerFile。

可以直接用该DockerFile,如果出现错误,极有可能是网络问题。试试更换pip源即可解决,也包括github上的包下不了改为gitee。

4. 源码BUG

开发过程中碰到一个BUG,只在python3.8环境下出现。具体情况如下:

在调用sentryApi时出现类型转换问题,在调用api参数转换时,出现URI参数时,进行了encode操作,使原来的string变为了bytes型,才出现错误。

我是这样修改的:

在apps/security/src/security/api/hive.py中

def _to_sentry_privilege(privilege):
  return {
      'privilegeScope': privilege['privilegeScope'],
      'serverName': privilege['serverName'],
      'dbName': privilege['dbName'],
      'tableName': privilege['tableName'],
      'columnName': privilege['columnName'],
      'URI': _massage_uri(privilege['URI'].encode('utf-8')),
      'action': privilege['action'],
      'createTime': privilege['timestamp'],
      'grantOption': 1 if privilege['grantOption'] else 0,
  }
  
  
def _hive_add_privileges(user, role, privileges):
    api = get_api(user)

    _privileges = []

    for privilege in privileges:
      if privilege['status'] not in ('deleted',):
        api.alter_sentry_role_grant_privilege(role['name'], _to_sentry_privilege(privilege))
        # Mocked until Sentry API returns the info. Not used currently as we refresh the whole role.
        _privileges.append({
            'timestamp': int(time.time()),
            'database': privilege.get('dbName'),
            'action': privilege.get('action'),
            'scope': privilege.get('privilegeScope'),
            'table': privilege.get('tableName'),
            'column': privilege.get('columnName'),
            # 'URI': privilege.get('URI').encode('utf-8'),
            'URI': privilege.get('URI'),
            'server': privilege.get('serverName'),
            'grantOption': privilege.get('grantOption') == 1
        })

    return _privileges

去掉了其中的“.encode('utf-8')”,问题解决,不知道合不合理,暂时解决吧。