iview-admin: 上传与下载

最近在使用iview-admin开发prometheus和alertmanager管理平台。prometheus管理规则我想可以通过下载当前页面规则到本地为excel文件,然后添加若干规则后上传更新。

1.下载规则为Excel文件

<template>
  <div>
    <Card>
      <Button icon="md-download" :loading="exportLoading" @click="exportExcel">导出规则</Button>
      <tables ref="tables" v-model="tableData" :columns="columns"/>
    </Card>
  </div>
</template>

<script>
import Tables from '_c/tables'
import {
  getPromRule
} from '@/api/data'
import excel from '@/libs/excel'

export default {
  name: 'rules',
  components: {
    Tables
  },
  data () {
    return {
      tableData: [],
      columns: [
        { title: '编号', align: 'center', key: 'id', sortable: true },
        { title: '告警名称', align: 'center', key: 'alert_name' },
        {
          title: '告警等级',
          align: 'center',
          key: 'severity',
          render: (h, params) => {
            if (params.row.severity === 'warning') {
              return h('div', '警告')
            } else if (params.row.severity === 'critical') {
              return h('div', '危急')
            } else if (params.row.severity === 'emergency') {
              return h('div', '紧急')
            }
          }
        },
        { title: '表达式', key: 'expr' },
        { title: '持续时长', align: 'center', key: 'duration' },
        { title: '标题', align: 'center', key: 'summary' },
        { title: '描述', align: 'center', key: 'description' },
        { title: '数据源', align: 'center', key: 'datasource' },
        { title: '告警策略', align: 'center', key: 'group' }
      ],
      exportLoading: false
    }
  },
  methods: {
    initRulesData () {
      this.filterPromRule()
    },
    filterPromRule () {
      getPromRule().then(resp => {
        if (resp.data.code === 0) {
          this.tableData = resp.data.data.prom_rules
        } else {
          this.$Message.error('获取prometheus规则失败!')
        }
      })
    },
    exportExcel () {
      if (this.tableData.length) {
        this.exportLoading = true
        let colTitle = []
        let colKey = []
        for (let col of this.columns) {
          if (col.title === '操作') {
            continue
          }
          colTitle.push(col.title)
          colKey.push(col.key)
        }
        const params = {
          title: colTitle,
          key: colKey,
          data: this.tableData,
          autoWith: true,
          filename: 'prometheus规则列表'
        }
        excel.export_array_to_excel(params)
        this.exportLoading = false
      } else {
        this.$Message.error('表格数据不能为空')
      }
    }
  },
  mounted () {
    this.initRulesData()
  }
}
</script>

<style>

</style>

2.上传EXCEL规则文件

上传文件的内容需要把数据放在数据库中并更新prometheus配置。

2.1 前台代码

<template>
  <div>
    <Card>
      <Upload action="" :before-upload="handleBeforeUpload" accept=".xls, .xlsx">
        <Button icon="ios-cloud-upload-outline" :loading="uploadLoading" @click="handleUploadFile">上传规则</Button>
      </Upload>
      <tables ref="tables" v-model="tableData" :columns="columns"/>
    </Card>
  </div>
</template>

<script>
import Tables from '_c/tables'
import {
  uploadPromRule,
  getPromRule
} from '@/api/data'
import excel from '@/libs/excel'

export default {
  name: 'rules',
  components: {
    Tables
  },
  data () {
    return {
      tableData: [],
      columns: [
        { title: '编号', align: 'center', key: 'id', sortable: true },
        { title: '告警名称', align: 'center', key: 'alert_name' },
        {
          title: '告警等级',
          align: 'center',
          key: 'severity',
          render: (h, params) => {
            if (params.row.severity === 'warning') {
              return h('div', '警告')
            } else if (params.row.severity === 'critical') {
              return h('div', '危急')
            } else if (params.row.severity === 'emergency') {
              return h('div', '紧急')
            }
          }
        },
        { title: '表达式', key: 'expr' },
        { title: '持续时长', align: 'center', key: 'duration' },
        { title: '标题', align: 'center', key: 'summary' },
        { title: '描述', align: 'center', key: 'description' },
        { title: '数据源', align: 'center', key: 'datasource' },
        { title: '告警策略', align: 'center', key: 'group' }
      ],
      uploadLoading: false
    }
  },
  methods: {
    initRulesData () {
      this.filterPromRule()
    },
    filterPromRule () {
      getPromRule().then(resp => {
        if (resp.data.code === 0) {
          this.tableData = resp.data.data.prom_rules
        } else {
          this.$Message.error('获取prometheus规则失败!')
        }
      })
    },
    handleBeforeUpload (file) {
      const fileExt = file.name.split('.').pop().toLocaleLowerCase()
      if (fileExt === 'xlsx' || fileExt === 'xls') {
        this.readFile(file)
        this.file = file
      } else {
        this.$Notice.warning({
          title: '文件类型错误',
          desc: '文件:' + file.name + '不是EXCEL文件,请选择后缀为.xlsx或者.xls的EXCEL文件。'
        })
      }
      return false
    },
    initUpload () {
      this.file = null
    },
    handleUploadFile () {
      this.initUpload()
    },
    readFile (file) {
      const reader = new FileReader()
      reader.readAsArrayBuffer(file)
      reader.onloadstart = e => {
        this.uploadLoading = true
        this.tableLoading = true
        this.showProgress = true
      }
      reader.onerror = e => {
        this.$Message.error('文件读取出错')
      }
      reader.onload = e => {
        this.$Message.info('文件读取成功')
        const data = e.target.result
        const { header, results } = excel.read(data, 'array')
        // eslint-disable-next-line no-unused-vars
        const tableTitle = header.map(item => { return { title: item, key: item } })
        uploadPromRule(results).then(resp => {
          if (resp.data.code === 0) {
            this.initRulesData()
          } else {
            this.$Message.error(resp.data.msg)
          }
        })
        this.uploadLoading = false
        this.tableLoading = false
      }
    }
  },
  mounted () {
    this.initRulesData()
  }
}
</script>

<style>

</style>

2.2 axios路由

// /src/api/data.js
export const uploadPromRule = (data) => {
  return axios.request({
    url: '/upload/prometheusconfigs',
    method: 'post',
    data
  })
}

2.3 后台路由

from .v1 import *

from flask_restful import Api

api = Api(prefix="/api/v1")
api.add_resource(PrometheusUploadView, "/upload/prometheusconfigs")

2.4后台业务逻辑代码

class PrometheusUploadView(RequestPrometheusBase):
    model = PromRulerModel

    def post(self):
        prom_rule_list = request.get_json(force=True)
        failed_title = ''
        if isinstance(prom_rule_list, list) and len(prom_rule_list) > 0:
            add_num = 0
            for rule in prom_rule_list:
                if "编号" in rule:
                    continue
                add_num += 1
                prom_rule_model = PromRulerModel()
                prom_rule_model.alert_name = rule["告警名称"]
                prom_rule_model.expr = rule["表达式"]
                prom_rule_model.duration = rule["持续时长"]
                prom_rule_model.severity = rule["告警等级"]
                prom_rule_model.summary = rule["标题"]
                prom_rule_model.description = rule["描述"]
                prom_rule_model.datasource = DataSourceModel.objects_().get_one(
                    DataSourceModel.name == rule["数据源"]).id
                prom_rule_model.group = GroupModel.objects_().get_one(GroupModel.name == rule["告警策略"]).id
                add_res = prom_rule_model.objects.add()
                if not add_res:
                    logger.error(f"Failed add prom rule when uploading!, Error: {rule['标题']} ")
                    failed_title = failed_title + ',' + rule['标题']
            if not failed_title:
                msg = "success"
            else:
                msg = f"上传数据失败!失败的标题有: {failed_title}"
                logger.error(msg)
            if add_num > 0:
                reload_res = self._reload_prom_config()
                reload_res['msg'] += msg
                return reload_res
        else:
            code = HttpCode.ERROR
            msg = "上传数据为空或者数据格式有问题!"
            logger.error(msg)
            return pretty_result(code=code, msg=msg)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值