DKube/service/deployment.go
2022-10-12 10:34:43 +08:00

280 lines
8.5 KiB
Go

package service
import (
"context"
"encoding/json"
"errors"
"github.com/wonderivan/logger"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"strconv"
"time"
)
var Deployment deployment
type deployment struct{}
type DeploymentsResp struct {
Items []appsv1.Deployment `json:"items"`
Total int `json:"total"`
}
type DeployCreate struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Replicas int32 `json:"replicas"`
Image string `json:"image"`
Label map[string]string `json:"label"`
Cpu string `json:"cpu"`
Memory string `json:"memory"`
ContainerPort int32 `json:"container_port"`
HealthCheck bool `json:"health_check"`
HealthPath string `json:"health_path"`
}
type DeploysNp struct {
Namespace string `json:"namespace"`
DeployNum int `json:"deployment_num"`
}
func (d *deployment) GetDeployments(filterName, namespace string, limit, page int) (deploymentsResp *DeploymentsResp, err error) {
deploymentList, err := K8s.ClientSet.AppsV1().Deployments(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
logger.Error(errors.New("获取Deployment列表失败, " + err.Error()))
return nil, errors.New("获取Deployment列表失败, " + err.Error())
}
selectableData := &dataSelector{
GenericDataList: d.toCells(deploymentList.Items),
DataSelect: &DataSelectQuery{
Filter: &FilterQuery{Name: filterName},
Paginate: &PaginateQuery{
Limit: limit,
Page: page,
},
},
}
filtered := selectableData.Filter()
total := len(filtered.GenericDataList)
data := filtered.Sort().Paginate()
deployments := d.fromCells(data.GenericDataList)
return &DeploymentsResp{
Items: deployments,
Total: total,
}, nil
}
func (d *deployment) GetDeploymentDetail(deploymentName, namespace string) (deployment *appsv1.Deployment, err error) {
deployment, err = K8s.ClientSet.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
if err != nil {
logger.Error(errors.New("获取Deployment详情失败, " + err.Error()))
return nil, errors.New("获取Deployment详情失败, " + err.Error())
}
return deployment, nil
}
func (d *deployment) ScaleDeployment(deploymentName, namespace string, scaleNum int) (replica int32, err error) {
scale, err := K8s.ClientSet.AppsV1().Deployments(namespace).GetScale(context.TODO(), deploymentName, metav1.GetOptions{})
if err != nil {
logger.Error(errors.New("获取Deployment副本数信息失败, " + err.Error()))
return 0, errors.New("获取Deployment副本数信息失败, " + err.Error())
}
scale.Spec.Replicas = int32(scaleNum)
newScale, err := K8s.ClientSet.AppsV1().Deployments(namespace).UpdateScale(context.TODO(), deploymentName, scale, metav1.UpdateOptions{})
if err != nil {
logger.Error(errors.New("更新Deployment副本数信息失败, " + err.Error()))
return 0, errors.New("更新Deployment副本数信息失败, " + err.Error())
}
return newScale.Spec.Replicas, nil
}
func (d *deployment) CreateDeployment(data *DeployCreate) (err error) {
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: data.Name,
Namespace: data.Namespace,
Labels: data.Label,
},
Spec: appsv1.DeploymentSpec{
Replicas: &data.Replicas,
Selector: &metav1.LabelSelector{
MatchLabels: data.Label,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: data.Name,
Labels: data.Label,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: data.Name,
Image: data.Image,
Ports: []corev1.ContainerPort{
{
Name: "http",
Protocol: corev1.ProtocolTCP,
ContainerPort: data.ContainerPort,
},
},
},
},
},
},
},
Status: appsv1.DeploymentStatus{},
}
if data.HealthCheck {
deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: data.HealthPath,
Port: intstr.IntOrString{
Type: 0,
IntVal: data.ContainerPort,
},
},
},
InitialDelaySeconds: 5,
TimeoutSeconds: 5,
PeriodSeconds: 5,
}
deployment.Spec.Template.Spec.Containers[0].LivenessProbe = &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: data.HealthPath,
Port: intstr.IntOrString{
Type: 0,
IntVal: data.ContainerPort,
},
},
},
InitialDelaySeconds: 15,
TimeoutSeconds: 5,
PeriodSeconds: 5,
}
}
deployment.Spec.Template.Spec.Containers[0].Resources.Limits = map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: resource.MustParse(data.Cpu),
corev1.ResourceMemory: resource.MustParse(data.Memory),
}
deployment.Spec.Template.Spec.Containers[0].Resources.Requests = map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: resource.MustParse(data.Cpu),
corev1.ResourceMemory: resource.MustParse(data.Memory),
}
_, err = K8s.ClientSet.AppsV1().Deployments(data.Namespace).
Create(context.TODO(), deployment, metav1.CreateOptions{})
if err != nil {
logger.Error(errors.New("创建Deployment失败, " + err.Error()))
return errors.New("创建Deployment失败, " + err.Error())
}
return nil
}
func (d *deployment) DeleteDeployment(deploymentName, namespace string) (err error) {
err = K8s.ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), deploymentName, metav1.DeleteOptions{})
if err != nil {
logger.Error(errors.New("删除Deployment失败, " + err.Error()))
return errors.New("删除Deployment失败, " + err.Error())
}
return nil
}
func (d *deployment) RestartDeployment(deploymentName, namespace string) (err error) {
patchData := map[string]interface{}{
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []map[string]interface{}{
{"name": deploymentName,
"env": []map[string]string{{
"name": "RESTART_",
"value": strconv.FormatInt(time.Now().Unix(), 10),
}},
},
},
},
},
},
}
patchByte, err := json.Marshal(patchData)
if err != nil {
logger.Error(errors.New("json序列化失败, " + err.Error()))
return errors.New("json序列化失败, " + err.Error())
}
_, err = K8s.ClientSet.AppsV1().Deployments(namespace).Patch(context.TODO(), deploymentName, "application/strategic-merge-patch+json", patchByte, metav1.PatchOptions{})
if err != nil {
logger.Error(errors.New("重启Deployment失败, " + err.Error()))
return errors.New("重启Deployment失败, " + err.Error())
}
return nil
}
func (d *deployment) UpdateDeployment(namespace, content string) (err error) {
var deploy = &appsv1.Deployment{}
err = json.Unmarshal([]byte(content), deploy)
if err != nil {
logger.Error(errors.New("反序列化失败, " + err.Error()))
return errors.New("反序列化失败, " + err.Error())
}
_, err = K8s.ClientSet.AppsV1().Deployments(namespace).Update(context.TODO(), deploy, metav1.UpdateOptions{})
if err != nil {
logger.Error(errors.New("更新Deployment失败, " + err.Error()))
return errors.New("更新Deployment失败, " + err.Error())
}
return nil
}
func (d *deployment) GetDeployNumPerNp() (deploysNps []*DeploysNp, err error) {
namespaceList, err := K8s.ClientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
for _, namespace := range namespaceList.Items {
deploymentList, err := K8s.ClientSet.AppsV1().Deployments(namespace.Name).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
deploysNp := &DeploysNp{
Namespace: namespace.Name,
DeployNum: len(deploymentList.Items),
}
deploysNps = append(deploysNps, deploysNp)
}
return deploysNps, nil
}
func (d *deployment) toCells(deployments []appsv1.Deployment) []DataCell {
cells := make([]DataCell, len(deployments))
for i := range deployments {
cells[i] = deploymentCell(deployments[i])
}
return cells
}
func (d *deployment) fromCells(cells []DataCell) []appsv1.Deployment {
deployments := make([]appsv1.Deployment, len(cells))
for i := range cells {
deployments[i] = appsv1.Deployment(cells[i].(deploymentCell))
}
return deployments
}