Django实现自动发布(3发布-升级和回退)

发布实际上就是将服务的某个版本和一台主机关联,我用一张表(MicroServiceInstance)记录了主机id、服务id、版本id,目前一台主机只能部署一个版本,所以主机id和服务id要做联合索引。

当我们操作某个实例时(升级、回退),为了防止其他人也进行相关操作,要对实例当前的状态就行判断,这里用 locked 标记。

升级、回退操作类似,都是更新MicroServiceInstance表记录的版本id,可以放在一个视图里实现。

升级回退页面

点击页面的版本管理,则弹出对应服务的版本列表页面,在这个页面可以进行发布操作,如下图:

然后点击某个版本的 升级回退 ,则弹出页面,用户可以选择需要目标版本和相应的主机:

由于获取主机相关的视图函数还未实现,所以页面显示了数据接口异常

当打开升级页面时,应该只能选择比当前版本高的版本,即id号大于当前id;同理回退页面则只能选择比当前版本低的版本,即id号小于当前id。而且用户只能选择构建成功的版本进行操作。

版本号下拉框的数据由后端返回:

class VersionDeployActionApi(generic.View):
    def get(self, request, service_id, action, pk):
        if action not in ('upgrade', 'revert'):
            return JsonResponse({'msg': '仅支持 upgrade/revert', 'code': -1}, status=417)

        cur_id = int(pk)
        versions = MicroServiceVersion.objects.filter(
            microservice_id=service_id,
            status=BuildStatus.success.value
        ).order_by('-id')

        data = [{
            'id': item.id,
            'version': item.version,
            'enable': item.id > cur_id if action == 'upgrade' else cur_id > item.id,
        } for item in versions]

        return JsonResponse({
            'data': data,
            'count': versions.count(),
            'code': 0,
        })

实例

页面上可供选择的实例,在数据库中体现为当前版本id关联的全部MicroServiceInstance对象,先在数据库中初始化一些对应关系

python manage.py shell
from microservice.models import *
MicroServiceInstance.objects.create(microservice_id=1, version_id=2, updated_by_id=1, host_id=1)

然后是返回当前版本下的全部实例:

class InstanceApi(generic.View):
    def get(self, request, service_id):
        query = request.GET
        version_id = query.get('version_id')
        locked = query.get('locked')

        try:
            service = MicroService.objects.get(pk=service_id)
        except MicroService.DoesNotExist:
            return JsonResponse({'msg': '资源不存在'}, status=404)

        insts = MicroServiceInstance.objects.filter(microservice=service)
        if version_id:
            insts = insts.filter(version_id=version_id)

        insts = insts.select_related('version').select_related('host').select_related('updated_by')

        if locked is not None:
            lck = False if locked in ('0', 'false') else True
            insts = insts.filter(locked=lck)

        data = [{
            'id': item.id,
            'name': service.name,
            'language': service.language,
            'version': item.version.version,
            'host': ':'.join((item.host.hostname, item.host.ip)),
            'host_id': item.host_id,
            'port': item.port,
            'tag': item.tag,
            'weight': item.weight,
            'description': item.description,
            'status': item.status,
            'status_str': item.get_status_display(),
            'is_maintain': item.is_maintain,
            'updated_by': item.updated_by.username,
            'updated': localtime(item.updated).strftime('%Y-%m-%d %H:%M:%S %Z'),
        } for item in insts]

        return JsonResponse({
            'data': data,
            'count': insts.count(),
            'code': 0,
        })

当lock为true时,代表实例正在被操作,前端查询时可以带上参数: lock=1,这样就只返回可进行发布的实例

执行升级/回退

页面选好了目标版本和对应的主机后,发送数据到后端,后端判断参数后执行相应的任务。

web开发有一条规则:永远不要相信用户的输入

为了保证服务实例数据的正确性、完整性,对用户提交的发布操作参数要进行严格校验:

  • 校验 service
  • 校验 version
  • 校验参数是否合法
  • 校验传入的主机id在数据库中是否有记录
  • 只更新db中存在且lock为false的实例

相关的代码实现:

# class VersionDeployActionApi 增加 post 方法

    def post(self, request, service_id, action, pk):
        params = request.POST
        q = {}
        q['dest_version'] = params.get('dest_version', '')
        q['host'] = params.get('host', '')

        if not q['dest_version']:
            return JsonResponse({'msg': '版本号不能为空'}, status=417)

        if not q['host']:
            return JsonResponse({'msg': '主机不能为空'}, status=417)
        else:
            if q['host'] != 'all' and (not re.match(r'[0-9,]', q['host'])):
                return JsonResponse({'msg': '主机参数错误,请传入 all 或以逗号分隔的id值'}, status=417)

        # 先获取服务
        try:
            service = MicroService.objects.get(pk=service_id)
            insts = MicroServiceInstance.objects.select_related('host').select_related('version').filter(version__id=pk)
            dest_ver = MicroServiceVersion.objects.filter(microservice=service).get(pk=q['dest_version'])
        except ObjectDoesNotExist:
            return JsonResponse({'msg': '资源不存在'}, status=404)

        db_idset = req_idset = set([x.host_id for x in insts])
        if q['host'] != 'all':
            req_idset = set([int(x) for x in q['host'].split(',') if x])
        # 如果传入的主机id在 db 中不存在
        if req_idset - db_idset:
            return JsonResponse({'msg': '请发送正确的主机id'}, status=404)

        # 只更新db中存在 且未锁定 的主机id
        idset = db_idset & req_idset

        st = InstanceStatus.upgrading.value if action == 'upgrade' else InstanceStatus.reverting.value
        for inst in insts:
            if inst.host_id in idset and not inst.locked:
                d = {
                    'updated_by': request.user,
                    'updated': now(),
                    'status': st,
                    'locked': True,
                }
                print d
                MicroServiceInstance.objects.filter(pk=inst.id).update(**d)

        # TODO 发起任务

        return JsonResponse({})

TODO 可以使用celery发起一个耗时的任务操作,而视图函数可以立即返回。

页面效果如下:

升级、回退,相关的代码在 这里

原文地址:https://www.cnblogs.com/wbjxxzx/p/12039094.html

时间: 2024-11-07 01:04:44

Django实现自动发布(3发布-升级和回退)的相关文章

Django实现自动发布(2视图-任务接收)

上一篇服务版本的新增,是通过触发 gitlab 任务来实现的,那么如何得到任务的最终状态呢? 好在 gitlab 为我们提供了webhook,也就是消息钩子,可以发送pipeline消息到我们指定的地址. 当我们收到消息后,就可以跟据任务的最终状态(成功or失败)来更新数据库里相应的版本: 失败时直接更新任务状态为失败 成功时除了更新状态,还要记录版本的路径 版本的存储路径 gitlab 的pipeline任务有一个递增的ID号,我们可以直接拿过来使用,以此ID为版本目录,打包好的服务就存放在该

【原创】我所理解的自动更新-APP发布与后台发布

发布后台 创建渠道:添加新的渠道,设置渠道名称,自动生成渠道id.    查看渠道:查看渠道基本信息,渠道app版本号,资源版本号,是否开启更新.    创建/更新APP:选择打包ios,android版本,设置渠道所属,设置版本日志,发送消息到APP Publish并等待反馈.    创建/更新资源:设置渠道所属,设置版本日志,发送消息到ResPackageTool并等待反馈. APP打包发布 从VersionServer里获取相应渠道的代码,保存到目录[channel-渠道号-版本号]. 

使用shell脚本自动部署(发布,重起)maven(java)项目

项目结构如下图 一:系统环境 本机:10.4.18.3 服务器: 10.4.18.4,用户名: web02 二:初始化服务器环境 在服务器上的家目录创建目录deploy,deploy/profile mkdir -p /home/web01/deploy mkdir -p /home/web02/deploy/profile 安装jdk export JAVA_HOME=/home/web02/jdk1.7.0_67 三:源代码(这里演示了一个自己写的http web服务器) com.lala.

通过TeamCity实现ASP.NET Core Web Application的自动编译及发布

下载 TeamCity,当前版本:2017.1 TeamCity插件:.NET Core Support .NET Core SDK,当前版本:1.0.1 安装 安装TeamCity.需要注意的地方: 安装路径 端口,这里是9080 安装Server和Agent Windows 服务的账号(这里建议使用系统账号而不是用户账号) 安装完成后会自动打开TeamCity的页面,开始初始化配置.数据目录,数据库和管理用用户. 安装TeamCity插件:.NET Core Support. 安装插件有两种

织梦DedeCMS信息发布员发布文章默认自动审核更新并生成HTML页面

织梦DedeCMS信息发布员发布文章默认自动审核更新并生成HTML页面 一直以为DEDECMS的信息发布员在后台发布文章后,非要管理员审核才能显示,今天一哥们问我这个问题.问:“能不能直接发布,并自动生成HTML,这样就节省了非要管理员来审核的麻烦?”我先跟他讲是不能的,非要管理员审核之后才能显示.呵呵,亏我用了这么长时间了,这么个简单的问题还回答的这么外行! 方法一:仔细研究了一下,是有办法的,让信息发布员的权限能够在发布文章之后自动生成HTML,并自动生成列表页和首页,具体办法如下: if(

jenkins自动构建与发布服务

安装jenkins构建使用插件 插件名 大概功能 Maven Integration plugin jenkins集成maven插件 Hudson Blame Subversion Plug-in 获取svn信息,数据同步 Subversion Partial Release Manager plugin svn版本发布管理器 Subversion Revert Plugin 构建失败时自动回滚svn Subversion Workspace Cleaner 清空svn工作空间 Deploy t

首富带你畅谈:蓝绿部署、滚动发布、灰度发布/金丝雀发布

首富带你畅谈:蓝绿部署.滚动发布.灰度发布/金丝雀发布 笔者: 张首富 时间: 2019-01-24晚 QQ群: 895291458 博客地址: www.zhangshoufu.com 根据2018年的DevOps发展报告来看,目前的DevOps发展速度非常之快,已经逐渐成为企业运维的标准方案.DevOps的核心就是敏捷和高效,敏捷和Scrum开发技术曾被认为是最好的技术.既然公司用到了CI/CD肯定就肯定避免不了持续部署,所以我们就需要考虑一套适合我们的发布方式,这个时候我们就需要了解一下这几

一文了解蓝绿发布/灰度发布/滚动发布

应用程序升级面临最大挑战是新旧业务切换,将软件从测试的最后阶段带到生产环境,同时要保证系统不间断提供服务. 长期以来,业务升级渐渐形成了几个发布策略:蓝绿发布.灰度发布和滚动发布,目的是尽可能避免因发布导致的流量丢失或服务不可用问题. 一. 蓝绿发布 项目逻辑上分为AB组,在项目系统时,首先把A组从负载均衡中摘除,进行新版本的部署.B组仍然继续提供服务. 当A组升级完毕,负载均衡重新接入A组,再把B组从负载列表中摘除,进行新版本的部署.A组重新提供服务. 最后,B组也升级完成,负载均衡重新接入B

jenkins+gitlab+微服务发布+k8s发布

背景:jenkins+gitlab+微服务发布+k8s发布实现自动更新1.配置jenkins pipeline pipeline语法`node {try {stage('代码拉取') {git credentialsId: 'xiongxj', url: '[email protected]:xinjiang.xiong/oam.git' } stage('项目构建') { sh " /opt/software/apache-maven-3.6.0/bin/mvn clean package&q