✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。
文章目录
- 接口优化
-
- [1. 首先先安装下kubeutils](#1. 首先先安装下kubeutils)
- [2. 使用接口改造controllers.go](#2. 使用接口改造controllers.go)
- [3. 创建pod功能实现](#3. 创建pod功能实现)
- [4. 查询pod列表功能实现](#4. 查询pod列表功能实现)
- [5. 获取pod详情功能实现](#5. 获取pod详情功能实现)
- [6. 更新pod功能](#6. 更新pod功能)
- [7. 删除单个pod和批量删除pod功能](#7. 删除单个pod和批量删除pod功能)
接口优化
观察前面我们开发的代码,我们发现,每种资源都有类似的增删改查逻辑,如果我们把这些类似的逻辑,做成统一的接口,就不用每种资源都需要写重复的代码了。
该怎么设计呢?
我们基于命名空间的struct,写增删改查方法,然后让各类资源去调用
我们使用一个接口工具来优化代码
接口工具地址:https://github.com/littlefun91/kubeutils
功能使用方法
1. 首先先安装下kubeutils
bash
go get -u github.com/littlefun91/kubeutils
2. 使用接口改造controllers.go
创建各种资源,都可以使用这里面通用的增删改查方法
go
// Package controllers 控制器层,实现路由的逻辑处理
package controllers
import (
"errors"
"github.com/gin-gonic/gin"
"github.com/littlefun91/kubeutils/kubeutils"
"jingtian/krm-backend/config"
"jingtian/krm-backend/utils/logs"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"net/http"
)
// BasicInfo 定义全局的数据结构
type BasicInfo struct {
//使用form标签指定参数名,以便正确地绑定参数 get请求使用功能form标签
ClusterId string `json:"clusterId" form:"clusterId"`
Namespace string `json:"namespace" form:"namespace"`
Name string `json:"name" form:"name"`
Item interface{} `json:"item"` //用来接收前端传来的更新资源的json串
DeleteList []string `json:"deleteList"` //用来接收前端传来的删除资源的json串,可以删一个,也可以删多个
}
type Info struct {
BasicInfo
ReturnData config.ReturnData
LabelSelector string `json:"labelSelector" form:"labelSelector"`
FieldSelector string `json:"fieldSelector" form:"fieldSelector"`
// 判断是否是强制删除
Force bool `json:"force" form:"force"`
}
// NewInfo 定义一个函数,用来返回kubeconfig
func NewInfo(c *gin.Context, info *Info, returnDataMsg string) (kubeconfig string) {
// 首先获取请求的类型
requestMethod := c.Request.Method
var err error
// var returnData config.ReturnData
info.ReturnData.Msg = returnDataMsg
info.ReturnData.Status = 200
if requestMethod == "GET" {
err = c.ShouldBindQuery(&info)
} else if requestMethod == "POST" {
err = c.ShouldBindJSON(&info)
} else {
err = errors.New("不支持的请求类型")
}
logs.Debug(map[string]interface{}{"info": info}, "数据绑定结果")
if err != nil {
msg := "请求出错: " + err.Error()
info.ReturnData.Msg = msg
info.ReturnData.Status = 400
logs.Error(nil, msg)
c.JSON(http.StatusOK, info.ReturnData)
return
}
// 获取kubeconfig
kubeconfig = config.ClusterKubeconfig[info.ClusterId]
//我们的接口工具只需要接收个kubeconfig文件就可以实现增删改查了
return kubeconfig
}
// Create Info中的增删改查方法,重写kubeutils中的增删改查方法
func (i *Info) Create(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
//Create里面传参是namespace
err := kubeUtilsInterface.Create(i.Namespace)
if err != nil {
msg := "创建失败: " + err.Error()
i.ReturnData.Msg = msg
i.ReturnData.Status = 400
logs.Error(nil, msg)
}
c.JSON(200, i.ReturnData)
}
func (i *Info) Update(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
err := kubeUtilsInterface.Update(i.Namespace)
if err != nil {
msg := "更新失败: " + err.Error()
i.ReturnData.Msg = msg
i.ReturnData.Status = 400
logs.Error(nil, msg)
}
r.JSON(200, i.ReturnData)
}
func (i *Info) List(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
items, err := kubeUtilsInterface.List(i.Namespace, i.LabelSelector, i.FieldSelector)
if err != nil {
msg := "查询失败: " + err.Error()
i.ReturnData.Msg = msg
i.ReturnData.Status = 400
logs.Error(nil, msg)
} else {
i.ReturnData.Data = make(map[string]interface{})
i.ReturnData.Data["items"] = items
}
c.JSON(200, i.ReturnData)
}
func (i *Info) Get(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
item, err := kubeUtilsInterface.Get(i.Namespace, i.Name)
if err != nil {
msg := "查询失败: " + err.Error()
i.ReturnData.Msg = msg
i.ReturnData.Status = 400
logs.Error(nil, msg)
} else {
i.ReturnData.Data = make(map[string]interface{})
i.ReturnData.Data["item"] = item
}
c.JSON(200, i.ReturnData)
}
func (i *Info) Delete(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
var gracePeriodSeconds int64
if i.Force {
// 强制删除
var s int64 = 0
gracePeriodSeconds = s
}
err := kubeUtilsInterface.Delete(i.Namespace, i.Name, &gracePeriodSeconds)
if err != nil {
msg := "删除失败: " + err.Error()
i.ReturnData.Msg = msg
i.ReturnData.Status = 400
logs.Error(nil, msg)
}
c.JSON(200, i.ReturnData)
}
func (i *Info) DeleteList(c *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
var gracePeriodSeconds int64
if i.Force {
// 强制删除
var s int64 = 0
gracePeriodSeconds = s
}
err := kubeUtilsInterface.DeleteList(i.Namespace, i.BasicInfo.DeleteList, &gracePeriodSeconds)
if err != nil {
msg := "删除失败: " + err.Error()
i.ReturnData.Msg = msg
i.ReturnData.Status = 400
logs.Error(nil, msg)
}
c.JSON(200, i.ReturnData)
}
// BasicInit 这个函数用来返回通用的clientset,集群信息和error
func BasicInit(c *gin.Context, item interface{}) (clientset *kubernetes.Clientset, basicInfo BasicInfo, err error) {
basicInfo = BasicInfo{}
//根据传参,来确定Item的类型,可以接收任意的资源
basicInfo.Item = item
// 首先获取请求的类型,根据不同的请求类型来使用不同的方式绑定数据
requestMethod := c.Request.Method
if requestMethod == "GET" {
err = c.ShouldBindQuery(&basicInfo)
} else if requestMethod == "POST" {
err = c.ShouldBindJSON(&basicInfo)
} else {
err = errors.New("不支持的请求类型")
}
logs.Debug(map[string]interface{}{"basicInfo": basicInfo}, "数据绑定结果")
if err != nil {
msg := "请求出错: " + err.Error()
return nil, basicInfo, errors.New(msg)
}
//如果前端不传namespace,就用默认的命名空间
if basicInfo.Namespace == "" {
basicInfo.Namespace = "default"
}
// 获取kubeconfig
kubeconfig := config.ClusterKubeconfig[basicInfo.ClusterId]
restConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(kubeconfig))
if err != nil {
msg := "解析kubeconfig错误: " + err.Error()
return nil, basicInfo, errors.New(msg)
}
//创建客户端
clientset, err = kubernetes.NewForConfig(restConfig)
if err != nil {
msg := "创建clientset失败: " + err.Error()
return nil, basicInfo, errors.New(msg)
}
return clientset, basicInfo, nil
}
3. 创建pod功能实现
pod/creaet.go
go
package pod
import (
"github.com/gin-gonic/gin"
"github.com/littlefun91/kubeutils/kubeutils"
"jingtian/krm-backend/controllers"
"jingtian/krm-backend/utils/logs"
corev1 "k8s.io/api/core/v1"
)
// Create 创建namespace函数
func Create(c *gin.Context) {
logs.Debug(nil, "创建pod")
var pod corev1.Pod
var info controllers.Info
info.Item = &pod
kubeconfig := controllers.NewInfo(c, &info, "pod创建成功")
//改为接口形式的创建
var kubeUtilser kubeutils.KubeUtilser
instance := kubeutils.NewPod(kubeconfig, &pod)
// 把实例复制给kubeUtilser
kubeUtilser = instance
// 使用kubeUtilser创建资源
info.Create(c, kubeUtilser)
}
执行创建请求
yaml
{
"clusterId":"cluster01",
"namespace":"jingtian",
"item": {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"labels": {
"app": "web6"
},
"name": "web6"
},
"spec": {
"containers": [
{
"env": [
{
"name": "GIN_MODE",
"value": "release"
},
{
"name": "LOG_LEVEL",
"value": "info"
}
],
"image": "web:v4",
"imagePullPolicy": "IfNotPresent",
"name": "myweb",
"ports": [
{
"containerPort": 8080,
"protocol": "TCP"
}
]
}
]
}
}
}
k8s集群查看,pod创建成功
4. 查询pod列表功能实现
go
package pod
import (
"github.com/gin-gonic/gin"
"github.com/littlefun91/kubeutils/kubeutils"
"jingtian/krm-backend/controllers"
"jingtian/krm-backend/utils/logs"
)
func List(c *gin.Context) {
logs.Debug(nil, "列出pod列表")
//声明结构体,用结构体的方法创建资源
var info controllers.Info
//newInfo里面传默认的returndata.msg
kubeconfig := controllers.NewInfo(c, &info, "pod查询成功")
var kubeUtilser kubeutils.KubeUtilser
instance := kubeutils.NewPod(kubeconfig, nil)
// 把实例复制给kubeUtilser
kubeUtilser = instance
// 使用kubeUtilser查询资源
info.List(c, kubeUtilser)
}
查询成功
5. 获取pod详情功能实现
go
package pod
import (
"github.com/gin-gonic/gin"
"github.com/littlefun91/kubeutils/kubeutils"
"jingtian/krm-backend/controllers"
"jingtian/krm-backend/utils/logs"
)
func Get(c *gin.Context) {
logs.Debug(nil, "获取pod详情")
//声明结构体,用结构体的方法创建资源
var info controllers.Info
//newInfo里面传默认的returndata.msg
kubeconfig := controllers.NewInfo(c, &info, "pod查询详情成功")
var kubeUtilser kubeutils.KubeUtilser
instance := kubeutils.NewPod(kubeconfig, nil)
// 把实例复制给kubeUtilser
kubeUtilser = instance
// 使用kubeUtilser查询资源
info.Get(c, kubeUtilser)
}
postman请求
6. 更新pod功能
一般,工作中我们也很少去更新pod。暂时不支持更新pod操作,响应给前端。
go
package pod
import (
"github.com/gin-gonic/gin"
"jingtian/krm-backend/config"
"jingtian/krm-backend/utils/logs"
)
func Update(c *gin.Context) {
logs.Debug(nil, "更新pod")
var returnData config.ReturnData
returnData.Msg = "Pod暂不支持更新操作"
returnData.Status = 200
c.JSON(200, returnData)
}
7. 删除单个pod和批量删除pod功能
go
package pod
import (
"github.com/gin-gonic/gin"
"github.com/littlefun91/kubeutils/kubeutils"
"jingtian/krm-backend/controllers"
"jingtian/krm-backend/utils/logs"
)
// Delete 删除命名空间
func Delete(c *gin.Context) {
logs.Debug(nil, "删除单个pod")
//声明结构体,用结构体的方法创建资源
var info controllers.Info
//newInfo里面传默认的returndata.msg
kubeconfig := controllers.NewInfo(c, &info, "pod删除成功")
var kubeUtilser kubeutils.KubeUtilser
instance := kubeutils.NewPod(kubeconfig, nil)
// 把实例复制给kubeUtilser
kubeUtilser = instance
// 使用kubeUtilser查询资源
info.Delete(c, kubeUtilser)
}
// DeleteList 批量删除
func DeleteList(c *gin.Context) {
logs.Debug(nil, "批量删除pod")
//声明结构体,用结构体的方法创建资源
var info controllers.Info
//newInfo里面传默认的returndata.msg
kubeconfig := controllers.NewInfo(c, &info, "pod批量删除成功")
var kubeUtilser kubeutils.KubeUtilser
instance := kubeutils.NewPod(kubeconfig, nil)
// 把实例复制给kubeUtilser
kubeUtilser = instance
// 使用kubeUtilser查询资源
info.DeleteList(c, kubeUtilser)
}
看下目前jingtian命名空间下的pod
postman执行删除单个pod
集群查看,删除单个pod成功
批量删除pod
集群查看,批量删除pod成功