1 Commits

Author SHA1 Message Date
dependabot[bot]
b512f98ed4 Bump apache-airflow from 1.10.3 to 2.4.2
Bumps [apache-airflow](https://github.com/apache/airflow) from 1.10.3 to 2.4.2.
- [Release notes](https://github.com/apache/airflow/releases)
- [Changelog](https://github.com/apache/airflow/blob/main/RELEASE_NOTES.rst)
- [Commits](https://github.com/apache/airflow/compare/1.10.3...2.4.2)

---
updated-dependencies:
- dependency-name: apache-airflow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-16 05:42:49 +00:00
13 changed files with 808 additions and 917 deletions

View File

@@ -1,248 +0,0 @@
[简体中文](README.md) | [English](README.en.md)
# Seal (海豹)
> django-base-templates — a Django development DEMO platform, supporting both non-separated (server-rendered) and separated (front-end / back-end) modes
![Version](https://img.shields.io/badge/release-0.3-blue.svg)
![Language](https://img.shields.io/badge/language-python3.6-blue.svg)
![Env](https://img.shields.io/badge/env-django2.2-red.svg)
![Bootstrap3](https://img.shields.io/badge/model-bootstrap3-mauve.svg)
![RESTful](https://img.shields.io/badge/api-RESTful-blue.svg)
![GraphQL](https://img.shields.io/badge/api-GraphQL-blue.svg)
> The project started on March 1st, which is International Seal Day, hence the name "Seal" (海豹).
## Introduction
Seal is a Django base development platform template built with the MVC pattern. It supports both **non-separated** development (Django template rendering) and **separated** development (RESTful / GraphQL APIs), so you can use it as a reference when building your own Django projects.
It is based on Django 2.2 + Python 3.6 + Celery 4 for async tasks, uses the Inspinia 2.7 front-end template (Bootstrap3), and is developed entirely with CBVs (Class-Based Views). It also ships with DRF RESTful API examples, GraphQL examples, Kubernetes management, and SQL audit/execution modules as real-world references.
Beyond being a base template, the project includes two complete ops-oriented implementations: a **K8s web console** (Node / Service / Pod lists + Pod WebSSH, executing commands via the Kubernetes API) and a **SQL audit & execution engine** (goInception / soar).
The author develops and updates this project on weekends.
## ✨ Features
- **Base development templates**: `base` web layout template + `system` platform pages (home / login / password change), front-end template Inspinia 2.7 (Bootstrap3)
- **Asset management example**: the `assets` app provides a complete CRUD (CBV) example to reference when developing your own modules
- **RESTful API**: DRF-based API examples with Token authentication (`/api/token`), plus two built-in API docs endpoints (`/api/docs/` and Swagger-style `/api/docs2/`)
- **GraphQL**: graphene-django Query / Mutation examples (user list, single query, create/update/delete) with a built-in GraphiQL playground (`/graphql/`)
- **Kubernetes management**: Node / Service / Pod lists and Pod details, plus **Pod WebSSH** (django-channels + WebSocket, executing commands inside Pods via the Kubernetes API)
- **SQL audit & execution**: goInception for SQL checking / execution (with backup support) and soar for SQL optimization advice; supports multiple database environments
- **Two async task options**: Celery (recommended for scheduled tasks, with django-celery-beat / django-celery-results / flower) and dramatiq (ordinary async tasks)
- **Permission control**: login authentication + Django Permission-based page-level checks; the Django admin is prettified with django-simpleui
## Roadmap
* Phase 1: base templates (done)
* Phase 2: Kubernetes management platform (in progress)
* node/service/pod lists (done)
* pod webssh (done, executing commands via the Kubernetes API)
* Phase 3: MySQL SQL statement audit (done)
* SQL check and execution
* Phase 4: in progress — rebuilding the front end <https://github.com/hequan2017/seal-d2-admin>
## 🛠 Tech Stack
**Backend**
- Python 3.6 / Django 2.2.4 (CBV style)
- Django REST framework 3.9.2 + django-rest-swagger (API and docs)
- graphene-django 2.2.0 (GraphQL)
- celery 4.1.1 + django-celery-beat + django-celery-results + flower; dramatiq 1.5.0 (async tasks)
- django-channels 2.2.0 + channels-redis (WebSocket channel for Pod WebSSH)
- kubernetes 9.0.0 (official Kubernetes Python client), PyMySQL / mysqlclient, paramiko, psutil
**Front-end**
- Bootstrap3 + Inspinia 2.7 template (non-separated mode)
- Vue-based front ends: <https://github.com/hequan2017/seal-vue> and <https://github.com/hequan2017/seal-d2-admin>
**Storage & services**
- MySQL 5.7 / SQLite
- Redis (broker and backend for celery / dramatiq / channels)
**SQL audit tools**
- goInception / soar (executables are bundled in the repo under `sql/bin/`)
## 🚀 Quick Start
Requirements: Python 3.6, MySQL 5.7 (or SQLite), Redis.
```bash
yum install python-devel mysql-devel python36-devel.x86_64 -y
git clone https://github.com/hequan2017/seal
cd seal
## Django 2.2 does not support older versions of SQLite. If you want to use
## SQLite for storage, please upgrade it following this blog post:
## https://www.jianshu.com/p/cdacf4b74646
python36 -m pip install -r requirements.txt
python36 manage.py makemigrations
python36 manage.py migrate
python36 manage.py createsuperuser
python36 manage.py runserver 0.0.0.0:8001
// Run in the background
// nohup python36 manage.py runserver 0.0.0.0:8001 >> /tmp/http.log 2>&1 &
```
### K8s Module
Edit the K8s settings in `seal/settings.py` (see `k8s/k8sApi/获取k8s admin token的方法.md` for how to get the admin token):
```python
## K8S
Token = "<dashboard-admin-token>"
APISERVER = 'https://192.168.100.111:6443'
```
### SQL Module
Enter the project directory `cd seal`. The backup server can be configured in `sql/bin/config/config.toml`; for details, search for goInception on GitHub:
```bash
chmod +x sql/bin/soar
chmod +x sql/bin/goInception
./sql/bin/goInception -config=sql/bin/config/config.toml
```
### Async Tasks
* Async option 1: Celery is recommended for scheduled tasks
```bash
cd seal
celery -B -A seal worker -l info
```
* Async option 2: dramatiq for ordinary async tasks
```bash
cd system/decorator/asynchronous/
dramatiq asynchronous --watch . --log-file /tmp/dramatiq.log
```
### Notes
* If you plan to use this in production, regenerate the SECRET_KEY in the settings file.
* Timezone: timezone support is enabled, so Django stores UTC times in the database and converts them to UTC+8 when you read them through the timezone API; Celery recognizes the timezone automatically.
```python
from django.utils import timezone
for i in Users.objects.all():
print(i.last_login) ## Reading the field directly returns a UTC time; handle it carefully if needed
print(timezone.localtime(i.last_login).strftime("%Y-%m-%d %H:%M:%S")) ## Format into local time
## 2019-03-05 06:41:18.040809+00:00
## 2019-03-05 14:41:18
```
## 📁 Directory Structure
```
seal/
├── assets/ # Asset management (CRUD example)
├── k8s/ # Kubernetes management (node/service/pod lists, pod detail, webssh)
├── sql/ # SQL audit & execution (goInception / soar; executables in bin/)
├── system/ # System module (login / users / password / async task examples)
├── document/ # Demo screenshots, SQL notes, coding standards
├── templates/ # Page templates (base/system/assets/k8s/sql)
├── static/ # Static assets (inspinia, ace, echarts, ueditor, etc.)
└── seal/ # Project configuration (settings / urls / schema / routing / celery)
```
## 📸 DEMO / Screenshots
> Demo: <http://129.28.156.219:8001>
> Account: admin Password: 1qaz.2wsx
> API docs: <http://129.28.156.219:8001/api/docs/>
![List](document/demo/1.jpg)
![Create](document/demo/2.jpg)
![API](document/demo/3.jpg)
![API](document/demo/4.jpg)
![API](document/demo/5.jpg)
![K8S](document/demo/6.jpg)
![K8S](document/demo/7.jpg)
![SQL](document/demo/8.jpg)
## 🔗 Related Projects
* **seal-vue**: Vue-based front end (in active development): <https://github.com/hequan2017/seal-vue>
* **seal-d2-admin**: Phase 4 front-end rebuild (D2Admin): <https://github.com/hequan2017/seal-d2-admin>
## GraphQL Examples
See `seal/schema.py` for the code. Endpoint: <http://localhost/graphql>
GraphQL request examples:
```
query{
users{
id,
username,
email
}
}
query{
singleUser(pk: 1){
username,
email
}
}
mutation createUser {
createUser (username: "test1") {
info {
id,
},
ok
}
}
mutation updateUser {
updateUser (pk:2,username: "test2") {
info {
id,
},
ok
}
}
mutation deleteUser {
deleteUser (pk:2) {
ok
}
}
```
## 📄 License
[MIT](LICENSE) © 2019 He Quan (何全)
## Support / Resources
* CBV documentation: <http://ccbv.co.uk/projects/Django/2.1/django.views.generic.edit/>
* GraphQL reference (Chinese): <https://passwo.gitbook.io/graphql/index/drf>
### Community
* For questions, join the QQ group: 620176501 <a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=bbe5716e8bd2075cb27029bd5dd97e22fc4d83c0f61291f47ed3ed6a4195b024"><img border="0" src="https://github.com/hequan2017/cmdb/blob/master/static/img/group.png" alt="django开发讨论群" title="django开发讨论群"></a>
* Feature requests, feedback, and contributions are welcome.
### Author
* 何全 (He Quan)

292
README.md
View File

@@ -1,9 +1,4 @@
[简体中文](README.md) | [English](README.en.md)
# 海豹 seal
> django-base-templates —— 主要为 Django 开发 DEMO,支持非前后端分离和前后端分离模式
# 海豹
![版本](https://img.shields.io/badge/release-0.3-blue.svg)
![语言](https://img.shields.io/badge/language-python3.6-blue.svg)
![语言](https://img.shields.io/badge/env-django2.2-red.svg)
@@ -11,161 +6,50 @@
![RESTful](https://img.shields.io/badge/api-RESTful-blue.svg)
![GraphQL](https://img.shields.io/badge/api-GraphQL-blue.svg)
> 因本项目开始时间为 3 月 1 日,是国际海豹日,故项目起名为 海豹 seal。
> django-base-templates
## 项目介绍
> 因本项目开始时间为3月1日,是 国际海豹日,故项目起名为 海豹 seal
海豹(seal)是一个 Django 基础开发平台模板,采用 MVC 模式开发,同时支持 **非前后端分离**(Django 模板渲染)和 **前后端分离**(RESTful / GraphQL API)两种开发方式,可以直接拿来参考开发自己的 Django 项目。
> 主要为 django 基础开发平台, MVC 模式 开发.支持 非前后端分离 和 前后端分离模式,可以拿来参考 开发 django项目
项目基于 Django 2.2 + Python 3.6 + Celery 4 异步任务,前端模板使用 inspinia 2.7(Bootstrap3),全部采用 CBV(Class-Based View)方式开发,并附带 DRF RESTful API 示例、GraphQL 示例、Kubernetes 管理和 SQL 审核执行等实战模块。
> 支持 RESTful 和 GraphQL
除了作为基础模板,项目还内置了两个运维场景的完整实现:**K8s Web Console**(Node / Service / Pod 列表 + Pod WebSSH,通过调用 k8s api 执行命令)和 **SQL 审核执行引擎**(goInception / soar)。
> 作者会在周末进行开发、更新。
作者会在周末进行开发、更新。
> 支持 k8s webssh 管理 pod! sql执行 !
## ✨ 功能特性
## 介绍
* 基于bootstrap3+django2.2 + python3.6+celery4 异步任务
* 前端模板 inspinia 2.7
* 采用cbv开发方式
* drf RESTful api 例子
* 前端 Vue版本
* GraphQL
* k8s管理
* sql执行 引擎 goInception / soar
- **基础开发模板**:base 网页基本模板 + system 平台基本网页(首页 / 登录 / 修改密码),前端模板 inspinia 2.7(Bootstrap3)
- **资产管理示例**:assets 模块提供完整的增删改查(CBV)范例,可作业务模块开发参考
- **RESTful API**:基于 DRF 的接口示例,支持 Token 认证(`/api/token`),自带两套 API 文档(`/api/docs/` 与 Swagger 风格的 `/api/docs2/`)
- **GraphQL**:基于 graphene-django 的 Query / Mutation 示例(用户列表、单查、增删改),内置 GraphiQL 调试页面(`/graphql/`)
- **K8s 管理**:Node / Service / Pod 列表、Pod 详情,**Pod WebSSH**(django-channels + WebSocket,通过调用 k8s api 在 Pod 内执行命令)
- **SQL 审核执行**:集成 goInception 做 SQL 检测 / 执行(支持备份),集成 soar 输出语法优化建议,支持多环境数据库配置
- **异步任务双方案**:Celery(推荐用于定时任务,配合 django-celery-beat / django-celery-results / flower)与 dramatiq(普通异步任务)
- **权限控制**:登录认证 + Django Permission 页面级权限校验,后台管理使用 django-simpleui 美化
## 开发计划
* 一期:基础模板(已完成)
* 二期:k8s 管理平台(开发中)
* node/service/pod 列表(已完成)
* pod webssh(已完成,通过调用 k8s api 进行执行命令)
* 三期:mysql sql 语句审核(已完成)
* sql 检测执行
* 四期:正在开发中,重构前端 <https://github.com/hequan2017/seal-d2-admin>
* 一期: 基础模板 (已完成)
* 二期: k8s管理平台 (开发中)
* node/service/pod 列表 (已完成)
* pod webssh (已完成, 通过调用 k8s api 进行执行命令)
* 三期: mysql sql语句审核(已完成)
* sql检测执行
* 四期:正在开发中  重构前端 https://github.com/hequan2017/seal-d2-admin
## DEMO
## 🛠 技术栈
> http://129.28.156.219:8001
**后端**
> 账户 admin 密码 1qaz.2wsx
- Python 3.6 / Django 2.2.4(CBV 开发方式)
- Django REST framework 3.9.2 + django-rest-swagger(API 与文档)
- graphene-django 2.2.0(GraphQL)
- celery 4.1.1 + django-celery-beat + django-celery-results + flower;dramatiq 1.5.0(异步任务)
- django-channels 2.2.0 + channels-redis(Pod WebSSH 的 WebSocket 通道)
- kubernetes 9.0.0(官方 k8s python client)、PyMySQL / mysqlclient、paramiko、psutil
> api文档地址 : http://129.28.156.219:8001/api/docs/
**前端**
- Bootstrap3 + inspinia 2.7 模板(非前后端分离模式)
- Vue 版本前端:<https://github.com/hequan2017/seal-vue>、<https://github.com/hequan2017/seal-d2-admin>
**存储与依赖服务**
- MySQL 5.7 / SQLite
- Redis(celery / dramatiq / channels 的 broker 与 backend)
**SQL 审核工具**
- goInception / soar(可执行文件已随仓库提供,位于 `sql/bin/`)
## 🚀 快速开始
环境要求:Python 3.6、MySQL 5.7(或 SQLite)、Redis。
```bash
yum install python-devel mysql-devel python36-devel.x86_64 -y
git clone https://github.com/hequan2017/seal
cd seal
## django 2.2 不支持低版本的 sqlite,如果想使用 sqlite 存储数据,
## 请根据这个博客 https://www.jianshu.com/p/cdacf4b74646 进行升级
python36 -m pip install -r requirements.txt
python36 manage.py makemigrations
python36 manage.py migrate
python36 manage.py createsuperuser
python36 manage.py runserver 0.0.0.0:8001
// 后台运行
// nohup python36 manage.py runserver 0.0.0.0:8001 >> /tmp/http.log 2>&1 &
```
### K8s 模块
修改 `seal/settings.py` 中 k8s 相关设置(Token 获取方法见 `k8s/k8sApi/获取k8s admin token的方法.md`):
```python
## K8S
Token = "<dashboard-admin-token>"
APISERVER = 'https://192.168.100.111:6443'
```
### SQL 模块
进入项目目录 `cd seal`,`sql/bin/config/config.toml` 里面可以设置备份服务器,详情可以 GitHub 搜索 goInception:
```bash
chmod +x sql/bin/soar
chmod +x sql/bin/goInception
./sql/bin/goInception -config=sql/bin/config/config.toml
```
### 异步任务
* 扩展功能-异步1:推荐定时任务用 celery
```bash
cd seal
celery -B -A seal worker -l info
```
* 扩展功能-异步2:普通异步任务用 dramatiq
```bash
cd system/decorator/asynchronous/
dramatiq asynchronous --watch . --log-file /tmp/dramatiq.log
```
### 注意
* 如果想直接拿来做生产项目,请重新生成一个 settings 文件里面的 SECRET_KEY
* 时区问题(因为开启了时区,Django 在数据库里面保存的是 UTC 时间,调用的时候会帮你转为东八区,celery 会自动识别时间):
```python
from django.utils import timezone
for i in Users.objects.all():
print(i.last_login) ## 直接读取时间,会是 utc 时间,未转换,如果需要处理请注意
print(timezone.localtime(i.last_login).strftime("%Y-%m-%d %H:%M:%S")) ## 时间格式化为正常时间
## 2019-03-05 06:41:18.040809+00:00
## 2019-03-05 14:41:18
```
## 📁 目录结构
```
seal/
├── assets/ # 资产管理(增删改查示例)
├── k8s/ # K8s 管理(node/service/pod 列表、Pod 详情、webssh)
├── sql/ # SQL 审核执行(goInception / soar,bin 目录含可执行文件)
├── system/ # 系统模块(登录/用户/密码/异步任务示例)
├── document/ # demo 截图、sql 说明、代码规范
├── templates/ # 页面模板(base/system/assets/k8s/sql)
├── static/ # 静态资源(inspinia、ace、echarts、ueditor 等)
└── seal/ # 项目配置(settings / urls / schema / routing / celery)
```
## 📸 DEMO / 截图
> DEMO:<http://129.28.156.219:8001>
> 账户 admin 密码 1qaz.2wsx
> API 文档地址:<http://129.28.156.219:8001/api/docs/>
> vue 前端地址1 <https://github.com/hequan2017/seal-vue> 持续开发中
![列表](document/demo/1.jpg)
![添加](document/demo/2.jpg)
@@ -176,17 +60,20 @@ seal/
![K8S](document/demo/7.jpg)
![SQL](document/demo/8.jpg)
## 🔗 相关项目
## templates
* **seal-vue**:Vue 版本前端(持续开发中):<https://github.com/hequan2017/seal-vue>
* **seal-d2-admin**:四期重构前端(D2Admin):<https://github.com/hequan2017/seal-d2-admin>
* base 网页基本模板
* system 平台基本网页(首页/登录/修改密码)
* assets 资产管理 (增删改查例子)
* document 代码规范
## GraphQL 使用示例
具体代码请参考 `seal/schema.py`,请求地址:<http://localhost/graphql>
## GraphQL
> 具体代码 请参考 seal/schema.py
GraphQL 请求参数:
> 请求地址 : <http://localhost/graphql>
> GraphQL 请求参数
```
query{
users{
@@ -228,20 +115,101 @@ mutation deleteUser {
}
```
## 📄 License
[MIT](LICENSE) © 2019 何全
## 部署
* mysql 5.7 / sqlite
* redis
```bash
yum install python-devel mysql-devel python36-devel.x86_64 -y
git clone https://github.com/hequan2017/seal
cd seal
## django 2.2 不支持 低版本的 sqlite,如果想使用sqlite 存储数据 ,请根据这个博客 https://www.jianshu.com/p/cdacf4b74646 进行升级
python36 -m pip install -r requirements.txt
python36 manage.py makemigrations
python36 manage.py migrate
python36 manage.py createsuperuser
python36 manage.py runserver 0.0.0.0:8001
//
nohup python36 manage.py runserver 0.0.0.0:8001 >> /tmp/http.log 2>&1 &
```
## k8s模块
> 修改settings k8s 相关设置
```
## K8S
Token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZGhobWMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiOThkMDcwZWItODc1Yy0xMWU5LWE1MzgtMDAwYzI5N2I0ZmU3Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.XDFpez2E84R_zlopt_uEHPvVGUtSavypyix6UcYJO3J4imHdJy7MEkfV-wltBA1H8x0TT2AW64rLlXaRJ8OkFWJ0myedfKdjnf7i0oLQ8j-7lw6rT3A0e2pKmpnOaBQfgzRm83-t2I5MMp3Iu9VNUiAbqQpjql4AKwRuJEEGCs99tKStUxzIsJKusmUHh9KAK4BAxySn9h16T2URZ7czLP4mty2crYWNV4KwSwFPthGhFPsl8mnet_hiV5k4me5a8frmXytOy64MmGW8w3TBgiM-7hBYSxt84QGGnyi84LU0EFgtLwBWEOTZeUKKQ6IkoAprMmNcSxX8WUJFlx_uJg"
APISERVER = 'https://192.168.100.111:6443'
```
## SQL模块
> 进入项目 cd seal
> sql/bin/config/config.toml 里面可以设置备份服务器,详情可以 github搜索 goInception
```
chmod +x sql/bin/soar
chmod +x sql/bin/goInception
./sql/bin/goInception -config=sql/bin/config/config.toml
```
## 异步任务
* 扩展功能-异步1 推荐 定时任务用celery
```bash
cd seal
celery -B -A seal worker -l info
```
* 扩展功能-异步2 普通异步任务 用 dramatiq
```bash
cd system/decorator/asynchronous/
dramatiq asynchronous --watch . --log-file /tmp/dramatiq.log
```
## 注意
* 如果想直接拿来做生产项目,请重新生成一个 settings 文件里面的 SECRET_KEY
* 时区问题
```python
##因为开启了时区,所以django在数据库里面保存的为 utc 时间, 调用的时候会帮你 转为 东八区, celery会自动识别时间
from django.utils import timezone
for i in Users.objects.all():
print(i.last_login) ## 直接读取时间,会是 utc时间,未转换, 如果需要处理 请注意
print(timezone.localtime(i.last_login).strftime("%Y-%m-%d %H:%M:%S")) ## 时间格式化为 正常时间
## 2019-03-05 06:41:18.040809+00:00
## 2019-03-05 14:41:18
```
## 售后服务
* cbv 中文文档 <http://ccbv.co.uk/projects/Django/2.1/django.views.generic.edit/>
* GraphQL 中文参考文档 <https://passwo.gitbook.io/graphql/index/drf>
* cbv 中文文档 <http://ccbv.co.uk/projects/Django/2.1/django.views.generic.edit/>
* GraphQL 中文参考文档 <https://passwo.gitbook.io/graphql/index/drf>
### 交流
* 有问题可以加 QQ 群:620176501 <a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=bbe5716e8bd2075cb27029bd5dd97e22fc4d83c0f61291f47ed3ed6a4195b024"><img border="0" src="https://github.com/hequan2017/cmdb/blob/master/static/img/group.png" alt="django开发讨论群" title="django开发讨论群"></a>
* 欢迎提出你的需求和意见,或者来加入到本项目中一起开发。
### 其他
* 有问题 可以加QQ群: 620176501 <a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=bbe5716e8bd2075cb27029bd5dd97e22fc4d83c0f61291f47ed3ed6a4195b024"><img border="0" src="https://github.com/hequan2017/cmdb/blob/master/static/img/group.png" alt="django开发讨论群" title="django开发讨论群"></a>
* 欢迎提出你的需求和意见,或者来加入到本项目中一起开发。
### 作者
* 何全
* 何全

View File

@@ -1,44 +1,154 @@
# seal 海豹 CMDB —— 依赖清单(2026-09 安全修复版)
# 说明:原文件为 2019 年的 pip freeze 全量快照,本版改为"直接依赖"清单,
# 传递依赖由 pip 自动解析;运行要求 Python >= 3.10。
# 安全升级:Django 5.2 / DRF 3.17 / channels 4 / celery 5;
# 移除未使用的 apache-airflow、tornado、GitPython、numpy、thrift、
# lxml、SQLAlchemy、Mako、Werkzeug、gevent、autobahn、ipython 等历史依赖。
# Web 框架
Django==5.2.16
djangorestframework==3.17.2
django-filter==25.2
drf-spectacular==0.28.0
django-bootstrap3==25.1
django-pure-pagination==0.3.0
django-simpleui==2024.4.1
django-cors-headers==4.9.0
# GraphQL
graphene-django==3.2.3
# Channels / WebSocket
channels==4.3.1
channels-redis==4.3.0
daphne==4.2.2
Twisted==26.4.0
# Celery 任务队列
celery==5.5.3
django-celery-beat==2.8.1
django-celery-results==2.6.0
python-crontab==3.3.0
# 异步任务
dramatiq==1.18.0
# 数据库
mysqlclient==2.2.7
PyMySQL==1.1.2
# 工具 / 客户端
requests==2.33.0
kubernetes==33.1.0
prettytable==3.16.0
gunicorn==23.0.0
aioredis==1.2.0
alembic==0.9.10
amqp==2.4.2
aniso8601==3.0.2
anyjson==0.3.3
apache-airflow==2.4.2
argh==0.26.2
asgi-redis==1.4.3
asgiref==3.1.2
asn1crypto==0.24.0
async-timeout==3.0.1
attrs==19.1.0
autobahn==19.6.2
Automat==0.7.0
Babel==2.7.0
backcall==0.1.0
bcrypt==3.1.6
billiard==3.5.0.5
cachetools==3.1.1
celery==4.1.1
certifi==2018.11.29
cffi==1.12.3
channels==2.2.0
channels-redis==2.4.0
chardet==3.0.4
Click==7.0
colorama==0.4.1
configparser==3.5.3
constantly==15.1.0
coreapi==2.3.3
coreschema==0.0.4
croniter==0.3.30
cryptography==2.7
daphne==2.3.0
decorator==4.3.0
defusedxml==0.6.0
dill==0.2.9
Django==2.2.4
django-bootstrap3==11.0.0
django-bootstrap4==0.0.7
django-celery-beat==1.4.0
django-celery-results==1.0.4
django-cors-headers==2.5.2
django-crispy-forms==1.7.2
django-filter==2.1.0
django-pure-pagination==0.3.0
django-simpleui==2.1.2.603
django-timezone-field==3.0
djangorestframework==3.9.2
docutils==0.14
dramatiq==1.5.0
flower==0.9.3
funcsigs==1.0.0
future==0.16.0
gevent==1.4.0
gitdb2==2.0.5
GitPython==2.1.11
google-auth==1.6.3
graphene==2.1.3
graphene-django==2.2.0
graphql-core==2.1
graphql-relay==0.4.5
greenlet==0.4.15
gunicorn==19.9.0
hiredis==1.0.0
hyperlink==19.0.0
idna==2.8
incremental==17.5.0
ipython==6.4.0
ipython-genutils==0.2.0
iso8601==0.1.12
itsdangerous==1.1.0
itypes==1.1.0
jedi==0.12.0
Jinja2==2.10
json-merge-patch==0.2
jsonfield==2.0.2
kombu==4.4.0
kubernetes==9.0.0
lockfile==0.12.2
lxml==4.3.4
Mako==1.0.12
Markdown==2.6.11
MarkupSafe==1.1.1
msgpack==0.6.1
msgpack-python==0.5.6
mysqlclient==1.3.14
numpy==1.16.4
oauthlib==3.0.1
openapi-codec==1.3.2
ordereddict==1.1
pandas==0.24.2
paramiko==2.4.2
parso==0.2.1
pathtools==0.1.2
pendulum==1.4.4
pexpect==4.6.0
pickleshare==0.7.4
prettytable==0.7.2
prometheus-client==0.2.0
promise==2.2.1
prompt-toolkit==1.0.15
psutil==5.6.3
ptyprocess==0.5.2
pyasn1==0.4.5
pyasn1-modules==0.2.5
pycparser==2.19
Pygments==2.2.0
PyHamcrest==1.9.0
PyMySQL==0.9.3
PyNaCl==1.3.0
python-crontab==2.3.6
python-daemon==2.1.2
python-dateutil==2.8.0
python-editor==1.0.4
python3-openid==3.1.0
pytz==2018.4
pytzdata==2019.1
PyYAML==5.1
redis==3.2.1
requests==2.21.0
requests-oauthlib==1.2.0
rsa==4.0
Rx==1.6.1
setproctitle==1.1.10
simplegeneric==0.8.1
simplejson==3.16.0
singledispatch==3.4.0.3
six==1.11.0
smmap2==2.0.5
SQLAlchemy==1.2.19
sqlparse==0.3.0
tabulate==0.8.3
tenacity==4.12.0
text-unidecode==1.2
thrift==0.11.0
tornado==5.1.1
traitlets==4.3.2
Twisted==19.2.1
txaio==18.8.1
tzlocal==1.5.1
unicodecsv==0.14.1
uritemplate==3.0.0
urllib3==1.24.1
vine==1.3.0
watchdog==0.8.3
watchdog-gevent==0.1.0
wcwidth==0.1.7
websocket-client==0.56.0
Werkzeug==0.14.1
WTForms==2.2.1
zope.deprecation==4.4.0
zope.interface==4.6.0
django-rest-swagger

View File

@@ -1,8 +1,7 @@
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "seal.settings")
django.setup()
# channels 4:ASGI 入口直接复用 seal/routing.py 中定义的 application
from seal.routing import application # noqa: E402
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "seal.settings")
django.setup()
application = get_default_application()

View File

@@ -1,35 +1,34 @@
from __future__ import absolute_import, unicode_literals
import os
from celery.schedules import crontab
from datetime import timedelta
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'seal.settings')
# celery 5 移除了 celery.platforms,允许 root 运行改用环境变量
os.environ.setdefault('C_FORCE_ROOT', 'true')
app = Celery('seal')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
##定时任务
app.conf.update(
beat_schedule={
'demo1': {
'task': 'system.tasks.system_demo',
'schedule': timedelta(seconds=10),
'args': [111]
},
'demo2': {
'task': 'system.tasks.system_demo',
'schedule': crontab(minute=00, hour=00, day_of_month=1),
'args': [222]
},
}
)
from __future__ import absolute_import, unicode_literals
import os
from celery.schedules import crontab
from datetime import timedelta
from celery import Celery, platforms
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'seal.settings')
app = Celery('seal')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
platforms.C_FORCE_ROOT = True
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
##定时任务
app.conf.update(
CELERYBEAT_SCHEDULE={
'demo1': {
'task': 'system.tasks.system_demo',
'schedule': timedelta(seconds=10),
'args': [111]
},
'demo2': {
'task': 'system.tasks.system_demo',
'schedule': crontab(minute=00, hour=00,day_of_month=1),
'args': [222]
},
}
)

View File

@@ -1,106 +1,105 @@
from system.models import Users
from graphene_django import DjangoObjectType
import graphene
# 相关文档 https://passwo.gitbook.io/graphql/index/drf
class UserType(DjangoObjectType):
class Meta:
model = Users
fields = "__all__"
class Query(graphene.ObjectType):
users = graphene.List(UserType)
# List == Field:
# List 返回结果会是遍历所有查询结果
# Field 返回结果只存在单个 (其中可添加参数, ex. pk)
single_user = graphene.Field(UserType, pk=graphene.Int())
# 定义函数名的格式: resolve_字段
# **kwargs 传递参数
# pk: 如果在字段中定义, 则方法参数中必含
def resolve_users(self, info, **kwargs):
return Users.objects.all()
def resolve_single_user(self, info, pk):
return Users.objects.get(id=pk)
class TQuery(Query, graphene.ObjectType):
pass
class CreateUser(graphene.Mutation):
class Arguments:
username = graphene.String(required=True)
info = graphene.Field(UserType)
ok = graphene.Boolean()
def mutate(self, info, **kwargs):
# print(info.context.user, '==当前用户==')
# kwargs 是传递参数中的变量
# user = info.context.user
user_obj = Users(**kwargs)
try:
user_obj.save()
ok = True
except Exception as e:
print(e)
ok = False
return CreateUser(ok=ok, info=user_obj)
class CMutation(object):
create_user = CreateUser.Field()
class UpdateUser(graphene.Mutation):
class Arguments:
username = graphene.String()
pk = graphene.Int(required=True)
info = graphene.Field(UserType)
ok = graphene.Boolean()
def mutate(self, info, **kwargs):
pk = kwargs.get('pk')
user_obj = Users.objects.get(id=pk)
if not user_obj:
return UpdateUser(ok=False)
user_obj.__dict__.update(**kwargs)
user_obj.save()
ok = True
return UpdateUser(ok=ok, info=user_obj)
class UMutation(object):
update_user = UpdateUser.Field()
class DeleteUser(graphene.Mutation):
class Arguments:
pk = graphene.Int()
ok = graphene.Boolean()
def mutate(self, info, **kwargs):
pk = kwargs.get('pk')
user = Users.objects.get(id=pk)
user.delete()
return DeleteUser(ok=True)
class DMutation(object):
delete_user = DeleteUser.Field()
class Mutations(CMutation, UMutation,DMutation,graphene.ObjectType):
pass
schema = graphene.Schema(query=TQuery, mutation=Mutations)
from system.models import Users
from graphene_django import DjangoObjectType
import graphene
# 相关文档 https://passwo.gitbook.io/graphql/index/drf
class UserType(DjangoObjectType):
class Meta:
model = Users
class Query(graphene.ObjectType):
users = graphene.List(UserType)
# List == Field:
# List 返回结果会是遍历所有查询结果
# Field 返回结果只存在单个 (其中可添加参数, ex. pk)
single_user = graphene.Field(UserType, pk=graphene.Int())
# 定义函数名的格式: resolve_字段
# **kwargs 传递参数
# pk: 如果在字段中定义, 则方法参数中必含
def resolve_users(self, info, **kwargs):
return Users.objects.all()
def resolve_single_user(self, info, pk):
return Users.objects.get(id=pk)
class TQuery(Query, graphene.ObjectType):
pass
class CreateUser(graphene.Mutation):
class Arguments:
username = graphene.String(required=True)
info = graphene.Field(UserType)
ok = graphene.Boolean()
def mutate(self, info, **kwargs):
# print(info.context.user, '==当前用户==')
# kwargs 是传递参数中的变量
# user = info.context.user
user_obj = Users(**kwargs)
try:
user_obj.save()
ok = True
except Exception as e:
print(e)
ok = False
return CreateUser(ok=ok, info=user_obj)
class CMutation(object):
create_user = CreateUser.Field()
class UpdateUser(graphene.Mutation):
class Arguments:
username = graphene.String()
pk = graphene.Int(required=True)
info = graphene.Field(UserType)
ok = graphene.Boolean()
def mutate(self, info, **kwargs):
pk = kwargs.get('pk')
user_obj = Users.objects.get(id=pk)
if not user_obj:
return UpdateUser(ok=False)
user_obj.__dict__.update(**kwargs)
user_obj.save()
ok = True
return UpdateUser(ok=ok, info=user_obj)
class UMutation(object):
update_user = UpdateUser.Field()
class DeleteUser(graphene.Mutation):
class Arguments:
pk = graphene.Int()
ok = graphene.Boolean()
def mutate(self, info, **kwargs):
pk = kwargs.get('pk')
user = Users.objects.get(id=pk)
user.delete()
return DeleteUser(ok=True)
class DMutation(object):
delete_user = DeleteUser.Field()
class Mutations(CMutation, UMutation,DMutation,graphene.ObjectType):
pass
schema = graphene.Schema(query=TQuery, mutation=Mutations)

View File

@@ -1,275 +1,301 @@
"""
Django settings for seal project.
Generated by 'django-admin startproject' using Django 2.1.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import os
import sys
import socket
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '#z!nrh$bn536iwb+#_9cp#lv3s(fdslwud(1()9he3qsnw@rzx'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'system.apps.SystemConfig',
'assets.apps.AssetsConfig',
'k8s.apps.K8sConfig',
'sql.apps.SqlConfig',
'bootstrap3',
'django_celery_results',
'django_celery_beat',
'rest_framework',
'rest_framework.authtoken',
'corsheaders',
'django_filters',
'graphene_django',
'channels',
'drf_spectacular',
]
GRAPHENE = {
'SCHEMA': 'seal.schema.schema'
}
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'seal.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'seal.wsgi.application'
AUTH_USER_MODEL = 'system.users'
AUTHENTICATION_BACKENDS = ('system.views.CustomBackend',) ## 重新登录验证,增加邮箱名字也可以用作登录
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
if socket.gethostname().endswith('seal'):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '192.168.100.50',
'PORT': '3306',
'NAME': 'seal',
'USER': 'root',
'PASSWORD': '123456',
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_AGE = 432000
LOGIN_URL = '/auth/login'
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
DATETIME_FORMAT = 'Y-m-d H:i:s'
DATE_FORMAT = 'Y-m-d'
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
# STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
# logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '[argus] %(levelname)s %(asctime)s %(module)s %(message)s'
}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'verbose'
},
},
'loggers': {
'tasks': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
'asset': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
},
}
# 表格table
PAGINATION_SETTINGS = {
'PAGE_RANGE_DISPLAYED': 3,
'MARGIN_PAGES_DISPLAYED': 2,
'SHOW_FIRST_PAGE_WHEN_INVALID': True,
}
# 表格table 一页 展示数据
DISPLAY_PER_PAGE = 15
## celery 4
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
# CELERY_RESULT_BACKEND = 'django-db'
CELERY_BROKER_URL = 'redis://localhost:6379/2'
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
CELERYD_CONCURRENCY = 4
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYD_MAX_TASKS_PER_CHILD = 10
CELERYD_FORCE_EXECV = True
# 设置默认不存结果
# CELERY_IGNORE_RESULT = True
CELERY_CREATE_MISSING_QUEUES = True
CELERY_DISABLE_RATE_LIMITS = True
CELERYD_TASK_SOFT_TIME_LIMIT = 600
CELERY_TASK_RESULT_EXPIRES = 600
CELERY_ENABLE_UTC = False
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
## 钉钉 报警机器人 地址 调用地方为 system.tasks.ding_ding_to_info
web_hook_url = ""
## rest api
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer' # 注释掉 可以关闭 api web界面
),
'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.AllowAny',
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
}
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
'*',
)
MIDDLEWARE_CLASSES = ('system.views.DisableCSRFCheck',)
## K8S
Token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tdDg4amwiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmU1NWQ0MWEtOTI0My0xMWU5LTgzNzAtMDAwYzI5N2I0ZmU3Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.ClrHiRBo9TD9qQGT5xeU-0-Cpqp0ZSQJd9-t3hD6B-YGiY-Al8zrgx8B05Ta9oUHS6cEOz_vYrqXDKm3XDFb6yTzOs5XTUTxvGUKIkZzgYI8aZxkCSYLZa-G-MtsnvbHaZj6XryPCAZhat70XFc0RVmHWC_LnGGzuAdpY2BgdaRHGERTTAYMkK8Ac8vV1s-E-lpsnU3jNgMRANp6v7C50ejjAYVTHnsCquJbIRM0uC7b5RhXbzRaOxNK33bDByDczYwgDIw1DKBaeXf3ABaJdcsQK138YxhrVUvDYy4o6j5obmGotGPrIv9XBhS7kgin289gTq5A6KT7aGmZjZPsYw"
APISERVER = 'https://192.168.100.111:6443'
# django-channels配置
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)],
},
},
}
# 配置ASGI
ASGI_APPLICATION = "seal.routing.application"
SPECTACULAR_SETTINGS = {
'TITLE': '海豹 API 文档',
'VERSION': '1.0.0',
'SERVE_INCLUDE_SCHEMA': False,
}
"""
Django settings for seal project.
Generated by 'django-admin startproject' using Django 2.1.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import os
import sys
import socket
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '#z!nrh$bn536iwb+#_9cp#lv3s(fdslwud(1()9he3qsnw@rzx'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'system.apps.SystemConfig',
'assets.apps.AssetsConfig',
'k8s.apps.K8sConfig',
'sql.apps.SqlConfig',
'bootstrap3',
'django_celery_results',
'django_celery_beat',
'rest_framework',
'rest_framework.authtoken',
'corsheaders',
'django_filters',
'graphene_django',
'channels',
'rest_framework_swagger',
]
GRAPHENE = {
'SCHEMA': 'seal.schema.schema'
}
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'seal.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'seal.wsgi.application'
AUTH_USER_MODEL = 'system.users'
AUTHENTICATION_BACKENDS = ('system.views.CustomBackend',) ## 重新登录验证,增加邮箱名字也可以用作登录
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
if socket.gethostname().endswith('seal'):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '192.168.100.50',
'PORT': '3306',
'NAME': 'seal',
'USER': 'root',
'PASSWORD': '123456',
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_AGE = 432000
LOGIN_URL = '/auth/login'
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = False
USE_TZ = True
DATETIME_FORMAT = 'Y-m-d H:i:s'
DATE_FORMAT = 'Y-m-d'
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
# STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
# logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '[argus] %(levelname)s %(asctime)s %(module)s %(message)s'
}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'verbose'
},
},
'loggers': {
'tasks': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
'asset': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
},
}
# 表格table
PAGINATION_SETTINGS = {
'PAGE_RANGE_DISPLAYED': 3,
'MARGIN_PAGES_DISPLAYED': 2,
'SHOW_FIRST_PAGE_WHEN_INVALID': True,
}
# 表格table 一页 展示数据
DISPLAY_PER_PAGE = 15
## celery 4
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
# CELERY_RESULT_BACKEND = 'django-db'
CELERY_BROKER_URL = 'redis://localhost:6379/2'
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
CELERYD_CONCURRENCY = 4
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYD_MAX_TASKS_PER_CHILD = 10
CELERYD_FORCE_EXECV = True
# 设置默认不存结果
# CELERY_IGNORE_RESULT = True
CELERY_CREATE_MISSING_QUEUES = True
CELERY_DISABLE_RATE_LIMITS = True
CELERYD_TASK_SOFT_TIME_LIMIT = 600
CELERY_TASK_RESULT_EXPIRES = 600
CELERY_ENABLE_UTC = False
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
## 钉钉 报警机器人 地址 调用地方为 system.tasks.ding_ding_to_info
web_hook_url = ""
## rest api
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer' # 注释掉 可以关闭 api web界面
),
'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.AllowAny',
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
}
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
'*',
)
MIDDLEWARE_CLASSES = ('system.views.DisableCSRFCheck',)
## K8S
Token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tdDg4amwiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmU1NWQ0MWEtOTI0My0xMWU5LTgzNzAtMDAwYzI5N2I0ZmU3Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.ClrHiRBo9TD9qQGT5xeU-0-Cpqp0ZSQJd9-t3hD6B-YGiY-Al8zrgx8B05Ta9oUHS6cEOz_vYrqXDKm3XDFb6yTzOs5XTUTxvGUKIkZzgYI8aZxkCSYLZa-G-MtsnvbHaZj6XryPCAZhat70XFc0RVmHWC_LnGGzuAdpY2BgdaRHGERTTAYMkK8Ac8vV1s-E-lpsnU3jNgMRANp6v7C50ejjAYVTHnsCquJbIRM0uC7b5RhXbzRaOxNK33bDByDczYwgDIw1DKBaeXf3ABaJdcsQK138YxhrVUvDYy4o6j5obmGotGPrIv9XBhS7kgin289gTq5A6KT7aGmZjZPsYw"
APISERVER = 'https://192.168.100.111:6443'
# django-channels配置
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)],
},
},
}
# 配置ASGI
ASGI_APPLICATION = "seal.routing.application"
SWAGGER_SETTINGS = {
# 基础样式
# 'SECURITY_DEFINITIONS': {
# "basic": {
# 'type': 'basic'
# }
# },
'USE_SESSION_AUTH': True,
'SECURITY_DEFINITIONS': {
'api_key': {
'type': 'apiKey',
'in': 'header',
'name': 'authorization'
}
},
# 如果需要登录才能够查看接口文档, 登录的链接使用restframework自带的.
# 'LOGIN_URL': '/api/v1/login/',
# 'LOGOUT_URL': 'rest_framework:logout',
# 'DOC_EXPANSION': None,
# 'SHOW_REQUEST_HEADERS':True,
# 'USE_SESSION_AUTH': True,
# 'DOC_EXPANSION': 'list',
# 接口文档中方法列表以首字母升序排列
'APIS_SORTER': 'alpha',
# 如果支持json提交, 则接口文档中包含json输入框
'JSON_EDITOR': True,
# 方法列表字母排序
'OPERATIONS_SORTER': 'alpha',
'VALIDATOR_URL': None,
}

View File

@@ -1,24 +1,30 @@
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from system.views import index
from rest_framework.authtoken import views
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from graphene_django.views import GraphQLView
from seal.schema import schema
urlpatterns = [
path('', index),
path('index', index, name="index"),
path('system/', include('system.urls', namespace='system')),
path('assets/', include('assets.urls', namespace='assets')),
path('k8s/', include('k8s.urls', namespace='k8s')),
path('admin/', admin.site.urls, ),
path('api/token', views.obtain_auth_token),
# Swagger UI 与 OpenAPI Schema(drf-spectacular,替代已停维的 django-rest-swagger)
path('api/docs/', SpectacularSwaggerView.as_view(url_name='docs2'), name="docs"),
path('api/docs2/', SpectacularAPIView.as_view(), name="docs2"),
path('graphql/', GraphQLView.as_view(graphiql=True, schema=schema)),
path('sql/', include('sql.urls', namespace='sql')),
]
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from system.views import index
from rest_framework.authtoken import views
from rest_framework.documentation import include_docs_urls
from graphene_django.views import GraphQLView
from seal.schema import schema
from rest_framework_swagger.views import get_swagger_view
schema_view = get_swagger_view(title='海豹 API 文档')
API_TITLE = '海豹 API 文档'
API_DESCRIPTION = '海豹 API 文档'
urlpatterns = [
path('', index),
path('index', index, name="index"),
path('system/', include('system.urls', namespace='system')),
path('assets/', include('assets.urls', namespace='assets')),
path('k8s/', include('k8s.urls', namespace='k8s')),
path('admin/', admin.site.urls, ),
path('api/token', views.obtain_auth_token),
path('api/docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION, authentication_classes=[],
permission_classes=[])),
path('api/docs2/', schema_view, name="docs"),
path('graphql/', GraphQLView.as_view(graphiql=True, schema=schema)),
path('sql/', include('sql.urls', namespace='sql')),
]

4
static/js/jquery-3.1.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,41 @@
from django.test import TestCase
# Create your tests here.
class SystemSmokeTest(TestCase):
"""基础冒烟测试:确认 system 应用可正常加载。"""
def test_import(self):
from system import views # noqa: F401
self.assertTrue(True)
from django.test import TestCase
# Create your tests here.
from datetime import timedelta, datetime
import airflow
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.operators.dummy_operator import DummyOperator
default_args = {
'owner': 'jifeng.si',
'depends_on_past': False,
# 'depends_on_past': True,
#'start_date': airflow.utils.dates.days_ago(2),
'start_date': datetime(2018, 5, 2),
'email': ['1219957063@qq.com'],
'email_on_failure': False,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
dag = DAG(
'example_hello_world_dag',
default_args=default_args,
description='my first DAG',
schedule_interval='*/25 * * * *',
start_date=datetime(2018, 5, 28)
)
dummy_operator = DummyOperator(task_id='dummy_task', dag=dag)
hello_operator = BashOperator(
task_id='sleep_task',
depends_on_past=False,
bash_command='echo `date` >> /home/py/test.txt',
dag=dag
)
dummy_operator >> hello_operator

View File

@@ -1,5 +1,5 @@
{% load static %}
<script src="{% static "js/jquery-3.7.1.min.js" %}" type="text/javascript" ></script>
<script src="{% static "js/jquery-3.1.1.min.js" %}" type="text/javascript" ></script>
<script src="{% static "js/bootstrap.min.js" %}"></script>
<script src="{% static "js/plugins/metisMenu/jquery.metisMenu.js" %}"></script>
<script src="{% static "js/plugins/slimscroll/jquery.slimscroll.min.js" %}"></script>

View File

@@ -48,7 +48,7 @@
</div>
<script src="{% static "js/jquery-3.7.1.min.js" %}"></script>
<script src="{% static "js/jquery-3.1.1.min.js" %}"></script>
<script src="{% static "js/bootstrap.min.js" %}"></script>